diff --git a/layer.txt b/layer.txt
new file mode 100644
index 00000000000..a5947189b91
--- /dev/null
+++ b/layer.txt
@@ -0,0 +1,48 @@
+* Card generation (extended card)
+
+VISUALIZATION
+
+*	arrange a "shift" of the viewport to select a layer
+-	and restriction on movement
++	each viewport has its own layer
+
+LOGICS
+
+dungeon:
+	unavailability:
+*		flood
+*		landscape change
+*		building
+*			houses
+*			trees
+*			water
+*			factories
+*			bridges
+*			tunnels
+*			airports
+*		roads at the intersection of layers
+?	generator
+?	rivers, cities
+*	edges (independent lifting, void)
+
+activity restriction
+synchronization of landscape changes
+
+GUI
+
+**	construction of a two-level station
+-	construction of a worm-hole from one layer to a neighbour layer
+**	work with the station (construction, removal / blocking of parts / cost)
+*	menu template for management / construction
+
++	add selection of number of layers
++	only show layer switches for available layers
+?	only show tiles of current layer
++	fix the coordinates in the "help area"
+-	fix the coordinates in the start screen
+-	signatures, station names (on all layers), effects (on the desired layer)
+
+BAGI
++	station deletion (departure)
+*	Expansion of the underground station does not work (when adding cells, a new one is added)
+-	GF. "jumps" (the non-editable part of the station changes randomly when the station is modified)
diff --git a/media/baseset/opntitle.dat b/media/baseset/opntitle.dat
index 264aaff60b5..9793856b761 100644
Binary files a/media/baseset/opntitle.dat and b/media/baseset/opntitle.dat differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0ccf650abfc..92f3505f59c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -205,6 +205,10 @@ add_files(
     landscape.h
     landscape_type.h
     language.h
+    layer.cpp
+    layer_func.h
+    layer_gui.h
+    layer_type.h
     livery.h
     main_gui.cpp
     map.cpp
@@ -442,6 +446,8 @@ add_files(
     tunnelbridge.h
     tunnelbridge_cmd.cpp
     tunnelbridge_map.h
+    underground_gui.cpp
+    underground_gui.h
     vehicle.cpp
     vehicle_base.h
     vehicle_cmd.cpp
diff --git a/src/base_station_base.h b/src/base_station_base.h
index 40543f1b8f6..ace01445a93 100644
--- a/src/base_station_base.h
+++ b/src/base_station_base.h
@@ -26,6 +26,13 @@ struct StationSpecList {
 
 
 /** StationRect - used to track station spread out rectangle - cheaper than scanning whole map */
+/*
+**	���� "layer"
+**	����������� ���������:
+**	"Rect" ������������� ������ ������� ���� (�����������)
+**	(������� ����� ������������� �� ����� ����, --
+**	Rect ��������� ��������������� ����� �������� ����)
+*/
 struct StationRect : public Rect {
 	enum StationRectMode
 	{
@@ -36,7 +43,7 @@ struct StationRect : public Rect {
 
 	StationRect();
 	void MakeEmpty();
-	bool PtInExtendedRect(int x, int y, int distance = 0) const;
+	bool PtInExtendedRect(int topx, int topy, int distance = 0) const;
 	bool IsEmpty() const;
 	CommandCost BeforeAddTile(TileIndex tile, StationRectMode mode);
 	CommandCost BeforeAddRect(TileIndex tile, int w, int h, StationRectMode mode);
diff --git a/src/clear_cmd.cpp b/src/clear_cmd.cpp
index 06953884e1f..eeaba3f87bf 100644
--- a/src/clear_cmd.cpp
+++ b/src/clear_cmd.cpp
@@ -12,6 +12,7 @@
 #include "command_func.h"
 #include "landscape.h"
 #include "genworld.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "water.h"
 #include "core/random_func.hpp"
@@ -98,8 +99,28 @@ static void DrawClearLandFence(const TileInfo *ti)
 	EndSpriteCombine();
 }
 
+static void DrawUndergroundTile_Clear(TileInfo *ti)
+{
+
+}
+
 static void DrawTile_Clear(TileInfo *ti)
 {
+	uint base_tile = TopTile(ti->tile);
+	uint underground_tile = DownTile(base_tile);
+
+	bool self_underground = IsUnderground(ti->tile);
+
+	bool have_canalization = IsTileType(base_tile, MP_HOUSE);
+	bool have_underground = !IsTileType(underground_tile, MP_CLEAR);
+
+	if (self_underground && !have_canalization)
+		DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
+
+	if (self_underground && have_canalization)
+		DrawGroundSprite(SPR_FLAT_GRASS_TILE + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
+
+	if (!self_underground)
 	switch (GetClearGround(ti->tile)) {
 		case CLEAR_GRASS:
 			DrawClearLandTile(ti, GetClearDensity(ti->tile));
@@ -124,6 +145,9 @@ static void DrawTile_Clear(TileInfo *ti)
 			break;
 	}
 
+	if (!self_underground && have_underground)
+		DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
+
 	DrawBridgeMiddle(ti);
 }
 
@@ -321,7 +345,7 @@ void GenerateClearTile()
 	SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
 	do {
 		IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
-		tile = RandomTile();
+		tile = TopTile(RandomTile());
 		if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
 	} while (--i);
 
@@ -329,7 +353,7 @@ void GenerateClearTile()
 	i = gi;
 	do {
 		uint32 r = Random();
-		tile = RandomTileSeed(r);
+		tile = TopTile(RandomTileSeed(r));
 
 		IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
 		if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp
index 857dc61ad95..388d9acd4e2 100644
--- a/src/console_cmds.cpp
+++ b/src/console_cmds.cpp
@@ -25,6 +25,7 @@
 #include "screenshot.h"
 #include "genworld.h"
 #include "strings_func.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "window_func.h"
 #include "date_func.h"
@@ -1067,6 +1068,7 @@ DEF_CONSOLE_CMD(ConRestart)
 	}
 
 	/* Don't copy the _newgame pointers to the real pointers, so call SwitchToMode directly */
+	_settings_game.game_creation.layers = FindFirstBit(LayerCount());
 	_settings_game.game_creation.map_x = MapLogX();
 	_settings_game.game_creation.map_y = FindFirstBit(MapSizeY());
 	_switch_mode = SM_RESTARTGAME;
diff --git a/src/disaster_vehicle.cpp b/src/disaster_vehicle.cpp
index 1244f99aba6..6d5defaace9 100644
--- a/src/disaster_vehicle.cpp
+++ b/src/disaster_vehicle.cpp
@@ -325,7 +325,7 @@ static bool DisasterTick_Ufo(DisasterVehicle *v)
 			return true;
 		}
 		if (++v->age < 6) {
-			v->dest_tile = RandomTile();
+			v->dest_tile = TopTile(RandomTile());
 			return true;
 		}
 		v->current_order.SetDestination(1);
@@ -572,12 +572,12 @@ static bool DisasterTick_Big_Ufo(DisasterVehicle *v)
 		}
 
 		if (++v->age < 6) {
-			v->dest_tile = RandomTile();
+			v->dest_tile = TopTile(RandomTile());
 			return true;
 		}
 		v->current_order.SetDestination(1);
 
-		TileIndex tile_org = RandomTile();
+		TileIndex tile_org = TopTile(RandomTile());
 		TileIndex tile = tile_org;
 		do {
 			if (IsPlainRailTile(tile) &&
@@ -958,7 +958,7 @@ void ReleaseDisastersTargetingVehicle(VehicleID vehicle)
 			if (v->current_order.GetDestination() != 0 && v->dest_tile == vehicle) {
 				/* Revert to target-searching */
 				v->current_order.SetDestination(0);
-				v->dest_tile = RandomTile();
+				v->dest_tile = TopTile(RandomTile());
 				GetAircraftFlightLevelBounds(v, &v->z_pos, nullptr);
 				v->age = 0;
 			}
diff --git a/src/genworld.cpp b/src/genworld.cpp
index c76fe309d9b..61cbe2b2abb 100644
--- a/src/genworld.cpp
+++ b/src/genworld.cpp
@@ -350,6 +350,6 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti
 
 	/* Centre the view on the map */
 	if (FindWindowById(WC_MAIN_WINDOW, 0) != nullptr) {
-		ScrollMainWindowToTile(TileXY(MapSizeX() / 2, MapSizeY() / 2), true);
+		ScrollMainWindowToTile(TileXY(MapSizeX() / 2, MapSizeY() / LayerCount() / 2), true);
 	}
 }
diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp
index 154097e722f..62fa1966ebf 100644
--- a/src/genworld_gui.cpp
+++ b/src/genworld_gui.cpp
@@ -16,6 +16,8 @@
 #include "window_func.h"
 #include "date_func.h"
 #include "sound_func.h"
+#include "map_type.h"
+#include "layer_type.h"
 #include "fios.h"
 #include "string_func.h"
 #include "widgets/dropdown_type.h"
@@ -79,6 +81,7 @@ static const NWidgetPart _nested_generate_landscape_widgets[] = {
 				/* Left column with labels. */
 				NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(0, 4, 0),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_MAPSIZE, STR_MAPGEN_MAPSIZE_TOOLTIP), SetFill(1, 1),
+                                       NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_UNDERGROUND_LAYER_COUNT, STR_NULL), SetFill(1, 1),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_LAND_GENERATOR, STR_NULL), SetFill(1, 1),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_NUMBER_OF_TOWNS, STR_NULL), SetFill(1, 1),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_TERRAIN_TYPE, STR_NULL), SetFill(1, 1),
@@ -95,6 +98,7 @@ static const NWidgetPart _nested_generate_landscape_widgets[] = {
 						NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_BY, STR_NULL), SetPadding(1, 0, 0, 0), SetFill(1, 1),
 						NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_MAPSIZE_Y_PULLDOWN), SetDataTip(STR_JUST_INT, STR_MAPGEN_MAPSIZE_TOOLTIP), SetFill(1, 0),
 					EndContainer(),
+					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_LAYER_COUNT_PULLDOWN), SetDataTip(STR_JUST_INT, STR_NULL), SetFill(1, 0),
 					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_LANDSCAPE_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
 					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_TOWN_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
 					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_TERRAIN_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
@@ -199,6 +203,7 @@ static const NWidgetPart _nested_heightmap_load_widgets[] = {
 				NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_HEIGHTMAP_NAME, STR_NULL), SetFill(1, 1),
 				NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_MAPSIZE, STR_NULL), SetFill(1, 1),
 				NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_HEIGHTMAP_ROTATION, STR_NULL), SetFill(1, 1),
+				NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_UNDERGROUND_LAYER_COUNT, STR_NULL), SetFill(1, 1),
 				NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_NUMBER_OF_TOWNS, STR_NULL), SetFill(1, 1),
 				NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_NUMBER_OF_INDUSTRIES, STR_NULL), SetFill(1, 1),
 				NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_QUANTITY_OF_RIVERS, STR_NULL), SetFill(1, 1),
@@ -216,6 +221,7 @@ static const NWidgetPart _nested_heightmap_load_widgets[] = {
 							NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_MAPSIZE_Y_PULLDOWN), SetDataTip(STR_JUST_INT, STR_NULL), SetFill(1, 0),
 						EndContainer(),
 						NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_HEIGHTMAP_ROTATION_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
+						NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_LAYER_COUNT_PULLDOWN), SetDataTip(STR_JUST_INT, STR_NULL), SetFill(1, 0),
 						NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_TOWN_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
 						NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_INDUSTRY_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
 						NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_RIVER_PULLDOWN), SetDataTip(STR_JUST_STRING, STR_NULL), SetFill(1, 0),
@@ -280,11 +286,11 @@ static void LandscapeGenerationCallback(Window *w, bool confirmed)
 	if (confirmed) StartGeneratingLandscape((GenerateLandscapeWindowMode)w->window_number);
 }
 
-static DropDownList BuildMapsizeDropDown()
+static DropDownList BuildBitListDropDown(uint min_bits, uint max_bits)
 {
 	DropDownList list;
 
-	for (uint i = MIN_MAP_SIZE_BITS; i <= MAX_MAP_SIZE_BITS; i++) {
+	for (uint i = min_bits; i <= max_bits; i++) {
 		DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false);
 		item->SetParam(0, 1LL << i);
 		list.emplace_back(item);
@@ -293,6 +299,16 @@ static DropDownList BuildMapsizeDropDown()
 	return list;
 }
 
+static DropDownList BuildMapsizeDropDown()
+{
+	return BuildBitListDropDown(MIN_MAP_SIZE_BITS, MAX_MAP_SIZE_BITS);
+}
+
+static DropDownList BuildLayerDropDown()
+{
+	return BuildBitListDropDown(MIN_LAYER_COUNT_BITS, MAX_LAYER_COUNT_BITS);
+}
+
 static const StringID _elevations[]  = {STR_TERRAIN_TYPE_VERY_FLAT, STR_TERRAIN_TYPE_FLAT, STR_TERRAIN_TYPE_HILLY, STR_TERRAIN_TYPE_MOUNTAINOUS, STR_TERRAIN_TYPE_ALPINIST, INVALID_STRING_ID};
 static const StringID _sea_lakes[]   = {STR_SEA_LEVEL_VERY_LOW, STR_SEA_LEVEL_LOW, STR_SEA_LEVEL_MEDIUM, STR_SEA_LEVEL_HIGH, STR_SEA_LEVEL_CUSTOM, INVALID_STRING_ID};
 static const StringID _rivers[]      = {STR_RIVERS_NONE, STR_RIVERS_FEW, STR_RIVERS_MODERATE, STR_RIVERS_LOT, INVALID_STRING_ID};
@@ -336,6 +352,7 @@ struct GenerateLandscapeWindow : public Window {
 			case WID_GL_START_DATE_TEXT:      SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); break;
 			case WID_GL_MAPSIZE_X_PULLDOWN:   SetDParam(0, 1LL << _settings_newgame.game_creation.map_x); break;
 			case WID_GL_MAPSIZE_Y_PULLDOWN:   SetDParam(0, 1LL << _settings_newgame.game_creation.map_y); break;
+			case WID_GL_LAYER_COUNT_PULLDOWN: SetDParam(0, 1 << _settings_newgame.game_creation.layers); break;
 			case WID_GL_MAX_HEIGHTLEVEL_TEXT: SetDParam(0, _settings_newgame.construction.max_heightlevel); break;
 			case WID_GL_SNOW_LEVEL_TEXT:      SetDParam(0, _settings_newgame.game_creation.snow_line_height); break;
 
@@ -458,6 +475,11 @@ struct GenerateLandscapeWindow : public Window {
 				*size = maxdim(*size, GetStringBoundingBox(STR_JUST_INT));
 				break;
 
+			case WID_GL_LAYER_COUNT_PULLDOWN:
+				SetDParam(0, MAX_LAYER_COUNT);
+				*size = GetStringBoundingBox(STR_JUST_INT);
+				break;
+
 			case WID_GL_SNOW_LEVEL_TEXT:
 				SetDParamMaxValue(0, MAX_TILE_HEIGHT);
 				*size = maxdim(*size, GetStringBoundingBox(STR_JUST_INT));
@@ -544,6 +566,10 @@ struct GenerateLandscapeWindow : public Window {
 				ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, WID_GL_MAPSIZE_Y_PULLDOWN);
 				break;
 
+			case WID_GL_LAYER_COUNT_PULLDOWN: // Mapsize Z
+				ShowDropDownList(this, BuildLayerDropDown(), _settings_newgame.game_creation.layers, WID_GL_LAYER_COUNT_PULLDOWN);
+				break;
+
 			case WID_GL_TOWN_PULLDOWN: // Number of towns
 				ShowDropDownMenu(this, _num_towns, _settings_newgame.difficulty.number_towns, WID_GL_TOWN_PULLDOWN, 0, 0);
 				break;
@@ -717,6 +743,7 @@ struct GenerateLandscapeWindow : public Window {
 		switch (widget) {
 			case WID_GL_MAPSIZE_X_PULLDOWN:     _settings_newgame.game_creation.map_x = index; break;
 			case WID_GL_MAPSIZE_Y_PULLDOWN:     _settings_newgame.game_creation.map_y = index; break;
+			case WID_GL_LAYER_COUNT_PULLDOWN:   _settings_newgame.game_creation.layers = index; break;
 			case WID_GL_TREE_PULLDOWN:          _settings_newgame.game_creation.tree_placer = index; break;
 			case WID_GL_RIVER_PULLDOWN:         _settings_newgame.game_creation.amount_of_rivers = index; break;
 			case WID_GL_SMOOTHNESS_PULLDOWN:    _settings_newgame.game_creation.tgen_smoothness = index;  break;
@@ -901,6 +928,10 @@ struct CreateScenarioWindow : public Window
 				SetDParam(0, 1LL << _settings_newgame.game_creation.map_y);
 				break;
 
+			case WID_CS_LAYER_COUNT_PULLDOWN:
+				SetDParam(0, 1 << _settings_newgame.game_creation.layers);
+				break;
+
 			case WID_CS_FLAT_LAND_HEIGHT_TEXT:
 				SetDParam(0, _settings_newgame.game_creation.se_flat_world_height);
 				break;
@@ -934,6 +965,10 @@ struct CreateScenarioWindow : public Window
 			case WID_CS_MAPSIZE_X_PULLDOWN:
 			case WID_CS_MAPSIZE_Y_PULLDOWN:
 				SetDParamMaxValue(0, MAX_MAP_SIZE);
+                               break;
+
+                       case WID_CS_LAYER_COUNT_PULLDOWN:
+                               SetDParam(0, MAX_LAYER_COUNT);
 				break;
 
 			case WID_CS_FLAT_LAND_HEIGHT_TEXT:
@@ -967,6 +1002,10 @@ struct CreateScenarioWindow : public Window
 				ShowDropDownList(this, BuildMapsizeDropDown(), _settings_newgame.game_creation.map_y, WID_CS_MAPSIZE_Y_PULLDOWN);
 				break;
 
+			case WID_CS_LAYER_COUNT_PULLDOWN: // Mapsize Y
+				ShowDropDownList(this, BuildLayerDropDown(), _settings_newgame.game_creation.layers, WID_CS_LAYER_COUNT_PULLDOWN);
+				break;
+
 			case WID_CS_EMPTY_WORLD: // Empty world / flat world
 				StartGeneratingLandscape(GLWM_SCENARIO);
 				break;
@@ -1029,6 +1068,7 @@ struct CreateScenarioWindow : public Window
 		switch (widget) {
 			case WID_CS_MAPSIZE_X_PULLDOWN: _settings_newgame.game_creation.map_x = index; break;
 			case WID_CS_MAPSIZE_Y_PULLDOWN: _settings_newgame.game_creation.map_y = index; break;
+			case WID_CS_LAYER_COUNT_PULLDOWN: _settings_newgame.game_creation.layers = index; break;
 		}
 		this->SetDirty();
 	}
@@ -1084,6 +1124,7 @@ static const NWidgetPart _nested_create_scenario_widgets[] = {
 					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_CS_MAPSIZE_X_PULLDOWN), SetDataTip(STR_JUST_INT, STR_NULL), SetPadding(0, 4, 0, 0),
 					NWidget(WWT_TEXT, COLOUR_ORANGE), SetDataTip(STR_MAPGEN_BY, STR_NULL), SetPadding(1, 2, 0, 0),
 					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_CS_MAPSIZE_Y_PULLDOWN), SetDataTip(STR_JUST_INT, STR_NULL),
+					NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_CS_LAYER_COUNT_PULLDOWN), SetDataTip(STR_JUST_INT, STR_NULL),
 				EndContainer(),
 				/* Date. */
 				NWidget(NWID_HORIZONTAL),
diff --git a/src/gfx_type.h b/src/gfx_type.h
index 6fca2228dfc..85fae182a36 100644
--- a/src/gfx_type.h
+++ b/src/gfx_type.h
@@ -155,6 +155,7 @@ struct DrawPixelInfo {
 	void *dst_ptr;
 	int left, top, width, height;
 	int pitch;
+	int layer;
 	ZoomLevel zoom;
 };
 
diff --git a/src/heightmap.cpp b/src/heightmap.cpp
index fab93c9802d..f345f5ee6d3 100644
--- a/src/heightmap.cpp
+++ b/src/heightmap.cpp
@@ -14,6 +14,7 @@
 #include "error.h"
 #include "saveload/saveload.h"
 #include "bmp.h"
+#include "layer_func.h"
 #include "gfx_func.h"
 #include "fios.h"
 #include "fileio_func.h"
@@ -395,6 +396,9 @@ void FixSlopes()
 	width   = MapSizeX();
 	height  = MapSizeY();
 
+	/* Layers height correct */
+	FixUndergroundHeights();
+
 	/* Top and left edge */
 	for (row = 0; (uint)row < height; row++) {
 		for (col = 0; (uint)col < width; col++) {
diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp
index bd1d28ef6c0..b32e9922fb0 100644
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -12,6 +12,7 @@
 #include "industry.h"
 #include "station_base.h"
 #include "landscape.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "command_func.h"
 #include "town.h"
@@ -1438,7 +1439,7 @@ static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTil
 		IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
 		TileIndex cur_tile = TileAddWrap(tile, it.ti.x, it.ti.y);
 
-		if (!IsValidTile(cur_tile)) {
+		if (!IsValidTile(cur_tile) || IsUnderground(cur_tile)) {
 			return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
 		}
 
@@ -2013,7 +2014,7 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
 					/* We should not have more than one Random() in a function call
 					 * because parameter evaluation order is not guaranteed in the c++ standard
 					 */
-					tile = RandomTile();
+					tile = TopTile(RandomTile());
 					/* Start with a random layout */
 					size_t layout = RandomRange((uint32)num_layouts);
 					/* Check now each layout, starting with the random one */
@@ -2154,7 +2155,7 @@ static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType c
 {
 	uint tries = try_hard ? 10000u : 2000u;
 	for (; tries > 0; tries--) {
-		Industry *ind = CreateNewIndustry(RandomTile(), type, creation_type);
+		Industry *ind = CreateNewIndustry(TopTile(RandomTile()), type, creation_type);
 		if (ind != nullptr) return ind;
 	}
 	return nullptr;
diff --git a/src/landscape.cpp b/src/landscape.cpp
index f09bdcafffe..8607d7aad06 100644
--- a/src/landscape.cpp
+++ b/src/landscape.cpp
@@ -33,6 +33,7 @@
 #include "framerate_type.h"
 #include <list>
 #include <set>
+#include "layer_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -812,10 +813,10 @@ void RunTileLoop()
 		0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8, 0x4004B2, 0x800B87
 	};
 	assert_compile(lengthof(feedbacks) == 2 * MAX_MAP_SIZE_BITS - 2 * MIN_MAP_SIZE_BITS + 1);
-	const uint32 feedback = feedbacks[MapLogX() + MapLogY() - 2 * MIN_MAP_SIZE_BITS];
+	const uint32 feedback = feedbacks[MapLogX() + MapLogY() - LayerCountLog() - 2 * MIN_MAP_SIZE_BITS];
 
 	/* We update every tile every 256 ticks, so divide the map size by 2^8 = 256 */
-	uint count = 1 << (MapLogX() + MapLogY() - 8);
+	uint count = 1 << (MapLogX() + MapLogY() - LayerCountLog() - 8);
 
 	TileIndex tile = _cur_tileloop_tile;
 	/* The LFSR cannot have a zeroed state. */
@@ -839,17 +840,23 @@ void RunTileLoop()
 
 void InitializeLandscape()
 {
-	for (uint y = _settings_game.construction.freeform_edges ? 1 : 0; y < MapMaxY(); y++) {
-		for (uint x = _settings_game.construction.freeform_edges ? 1 : 0; x < MapMaxX(); x++) {
-			MakeClear(TileXY(x, y), CLEAR_GRASS, 3);
-			SetTileHeight(TileXY(x, y), 0);
-			SetTropicZone(TileXY(x, y), TROPICZONE_NORMAL);
-			ClearBridgeMiddle(TileXY(x, y));
+	uint maxx = LayerMaxX();
+	uint maxy = LayerMaxY();
+	uint sizex = MapSizeX();
+	uint layersize = LayerSize();
+
+	FOR_ALL_LAYERS(layer) {
+		for (uint y = _settings_game.construction.freeform_edges ? 1 : 0; y < LayerMaxY(); y++) {
+			for (uint x = _settings_game.construction.freeform_edges ? 1 : 0; x < LayerMaxX(); x++) {
+				MakeClear(layer * layersize + TileXY(x, y), CLEAR_GRASS, 3);
+				SetTileHeight(layer * layersize + TileXY(x, y), 0);
+				SetTropicZone(layer * layersize + TileXY(x, y), TROPICZONE_NORMAL);
+				ClearBridgeMiddle(layer * layersize + TileXY(x, y));
+			}
+			MakeVoid(layer * layersize + TileXY(LayerMaxX(), y));
 		}
+		for (uint x = 0; x < LayerSizeX(); x++) MakeVoid(TileXY(x, LayerMaxY()));
 	}
-
-	for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, MapMaxY()));
-	for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(MapMaxX(), y));
 }
 
 static const byte _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4  };
@@ -1277,7 +1284,7 @@ static void CreateRivers()
 	for (; wells != 0; wells--) {
 		IncreaseGeneratingWorldProgress(GWP_RIVER);
 		for (int tries = 0; tries < 128; tries++) {
-			TileIndex t = RandomTile();
+			TileIndex t = TopTile(RandomTile());
 			if (!CircularTileSearch(&t, 8, FindSpring, nullptr)) continue;
 			if (FlowRiver(t, t)) break;
 		}
diff --git a/src/lang/afrikaans.txt b/src/lang/afrikaans.txt
index c478322ea09..080a0fe81e1 100644
--- a/src/lang/afrikaans.txt
+++ b/src/lang/afrikaans.txt
@@ -2616,7 +2616,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Tremweg
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Spoorweg eienaar: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Plaaslike raad: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Geen
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koördinate: {LTBLUE}{NUM}x{NUM}x{NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koördinate: {LTBLUE}{NUM}x{NUM}x{NUM}x-{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Gebou: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stasie klas: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stasie tiepe: {LTBLUE}{STRING}
diff --git a/src/lang/arabic_egypt.txt b/src/lang/arabic_egypt.txt
index 64d0491380a..293e2ee31cd 100644
--- a/src/lang/arabic_egypt.txt
+++ b/src/lang/arabic_egypt.txt
@@ -2198,7 +2198,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}مالك
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}مالك سكة الحديد: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}السلطة المحلية: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :فارغ
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}الأحداثيات: {LTBLUE}{NUM}x{NUM}x{NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}الأحداثيات: {LTBLUE}{NUM}x{NUM}x{NUM}x-{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}بني: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK} فئة المحطة: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}نوع المحطة: {LTBLUE}{STRING}
diff --git a/src/lang/basque.txt b/src/lang/basque.txt
index 4850567875d..4b36208dc4a 100644
--- a/src/lang/basque.txt
+++ b/src/lang/basque.txt
@@ -2474,7 +2474,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Tranbia
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Trenbidearen jabea: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Udaletxea {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Ezer ez
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordenadak: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordenadak: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Eraikia: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Geltoki mota: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Geltoki mota: {LTBLUE}{STRING}
diff --git a/src/lang/belarusian.txt b/src/lang/belarusian.txt
index 19f88d555e8..023129584e0 100644
--- a/src/lang/belarusian.txt
+++ b/src/lang/belarusian.txt
@@ -2942,7 +2942,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Улад
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Уладальнiк чыгункi: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Мясцовая адміністрацыя: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Няма
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Каардынаты: {LTBLUE}{NUM}x{NUM}x{NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Каардынаты: {LTBLUE}{NUM}x{NUM}x{NUM}x-{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Пабудавана: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Кляса станцыі: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Тып станцыi: {LTBLUE}{STRING}
diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt
index fc27d762827..76c963b12ff 100644
--- a/src/lang/brazilian_portuguese.txt
+++ b/src/lang/brazilian_portuguese.txt
@@ -2580,7 +2580,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Dono da
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Dono da linha ferroviária: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Prefeitura: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Nenhum
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenadas: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenadas: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Construído: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Classe de Estação: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Tipo de Estação: {LTBLUE}{STRING}
diff --git a/src/lang/bulgarian.txt b/src/lang/bulgarian.txt
index 5196ae47efe..a136f727010 100644
--- a/src/lang/bulgarian.txt
+++ b/src/lang/bulgarian.txt
@@ -2528,7 +2528,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Собс
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Собственик на железопътната линия: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Община: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Нищо
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Координати: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Координати: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Построен: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Клас на станцията: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Тип на станцията: {LTBLUE}{STRING}
diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt
index f4012ca12e7..3d423b63d15 100644
--- a/src/lang/catalan.txt
+++ b/src/lang/catalan.txt
@@ -2609,7 +2609,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Propieta
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Propietari del rail: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Autoritat Local: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Cap
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenades: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenades: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Construït: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Classe d'estació: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Tipus d'estació: {LTBLUE}{STRING}
diff --git a/src/lang/croatian.txt b/src/lang/croatian.txt
index 1a81252d4a8..24af796e3bf 100644
--- a/src/lang/croatian.txt
+++ b/src/lang/croatian.txt
@@ -2721,7 +2721,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Vlasnik
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Vlasnik željeznice: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Područna nadležnost: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Nijedan/Nitko/Ništa
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinate: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinate: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Izgrađeno: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Klasa postaje: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Vrsta postaje: {LTBLUE}{STRING}
diff --git a/src/lang/czech.txt b/src/lang/czech.txt
index 2dfe6c4aefa..d6e89ed76da 100644
--- a/src/lang/czech.txt
+++ b/src/lang/czech.txt
@@ -2717,7 +2717,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Majitel
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Majitel tratě: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Místní správa: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Nic
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Souřadnice: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Souřadnice: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Postaveno: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Třída stanice: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Druh stanice: {LTBLUE}{STRING}
diff --git a/src/lang/danish.txt b/src/lang/danish.txt
index b284d0f60fd..a290ff8ebde 100644
--- a/src/lang/danish.txt
+++ b/src/lang/danish.txt
@@ -2625,7 +2625,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Ejer af
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Ejer af jernbane: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Lokal myndighed: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Ingen
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinater: {LTBLUE}{NUM}x{NUM}x{NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinater: {LTBLUE}{NUM}x{NUM}x{NUM}x-{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Produceret: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stationsklasse: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stationstype: {LTBLUE}{STRING}
diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt
index 3d4a0f7d12d..48eecbd906f 100644
--- a/src/lang/dutch.txt
+++ b/src/lang/dutch.txt
@@ -2625,7 +2625,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Eigenaar
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Eigenaar van spoorweg: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Gemeente: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Geen
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coördinaten: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coördinaten: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Bouwjaar: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stationsklasse: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stationstype: {LTBLUE}{STRING}
diff --git a/src/lang/english.txt b/src/lang/english.txt
index c055f54a059..0050bdb6692 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -462,6 +462,18 @@ STR_LANDSCAPING_MENU_PLANT_TREES                                :Plant trees
 STR_LANDSCAPING_MENU_PLACE_SIGN                                 :Place sign
 ############ range ends here
 
+############ range for underground menu starts
+STR_LANDSCAPING_MENU_UNDERGROUND                                :Special constructions
+STR_LANDSCAPING_MENU_LAYER_1                                    :Surface
+STR_LANDSCAPING_MENU_LAYER_2                                    :Undergroound (-1)
+STR_LANDSCAPING_MENU_LAYER_3                                    :Undergroound (-2)
+STR_LANDSCAPING_MENU_LAYER_4                                    :Undergroound (-3)
+STR_LANDSCAPING_MENU_LAYER_5                                    :Undergroound (-4)
+STR_LANDSCAPING_MENU_LAYER_6                                    :Undergroound (-5)
+STR_LANDSCAPING_MENU_LAYER_7                                    :Undergroound (-6)
+STR_LANDSCAPING_MENU_LAYER_8                                    :Undergroound (-7)
+############ range ends here
+
 ############ range for music menu starts
 STR_TOOLBAR_SOUND_MUSIC                                         :Sound/music
 ############ range ends here
@@ -2625,7 +2637,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Tramway
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Railway owner: {LTBLUE}{STRING1}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Local authority: {LTBLUE}{STRING1}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :None
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordinates: {LTBLUE}{NUM} x {NUM} x {NUM} ({RAW_STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordinates: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({RAW_STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Built: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Station class: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Station type: {LTBLUE}{STRING}
@@ -5149,3 +5161,35 @@ STR_PLANE                                                       :{BLACK}{PLANE}
 STR_SHIP                                                        :{BLACK}{SHIP}
 
 STR_TOOLBAR_RAILTYPE_VELOCITY                                   :{STRING} ({VELOCITY})
+
+#	underground
+
+#	error
+STR_ERROR_UNDERGROUND_CAN_T_BUILD_UNDER_GROUND			    	:{WHITE}Can't build this underground
+STR_ERROR_UNDERGROUND_CAN_T_BUILD_OVER_GROUND					:{WHITE}Can't build this on surface
+STR_ERROR_UNDERGROUND_CAN_T_TERRAFORM							:{WHITE}Can't terraform underground
+STR_ERROR_UNDERGROUND_CAN_T_BUILD_PART                          :{WHITE}Can't build escalator here...
+STR_ERROR_UNDERGROUND_CAN_T_BUILD_TOP_PART                      :{WHITE}Can't build escalator top here...
+STR_ERROR_UNDERGROUND_CAN_T_BUILD_BOTTOM_PART                   :{WHITE}Can't build escalator bottom here...
+
+#	menus
+STR_UNDERGROUND_LAYER_COUNT										:{BLACK}Layers count
+STR_UNDERGROUND_BUILD											:{WHITE}Underground
+
+#	underground land types
+STR_UNDERGROUND_FLAT											:Cave
+STR_UNDERGROUND_SOLID											:Ground
+STR_UNDERGROUND_ROCKS											:Rocks
+STR_UNDERGROUND_HEAVY_ROCKS										:Hard rocks
+
+#	underground special build types
+STR_UNDERGROUND_ESCALATOR										:Escalator
+STR_UNDERGROUND_CONNECT											:Connect
+STR_UNDERGROUND_PIPE											:Pipe
+
+#	underground tool tip
+STR_UNDERGROUND_TOOLTIP_ESCALATOR								:{BLACK}Build escalator (underground station connect with surface)
+STR_UNDERGROUND_TOOLTIP_CONNECT									:{BLACK}Build connect (underground track connect with surface)
+STR_UNDERGROUND_TOOLTIP_PIPE									:{BLACK}Pipe (xm... anything...)
+
+#	end underground string
diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt
index 17a9659fbe2..17784608cc0 100644
--- a/src/lang/english_AU.txt
+++ b/src/lang/english_AU.txt
@@ -2537,7 +2537,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Tramway
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Railway owner: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Local authority: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :None
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordinates: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordinates: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Built: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Station class: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Station type: {LTBLUE}{STRING}
diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt
index 4eeb8b8fb97..9b4d4ba3843 100644
--- a/src/lang/english_US.txt
+++ b/src/lang/english_US.txt
@@ -2621,7 +2621,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Streetca
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Railroad owner: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Local authority: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :None
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Co-ordinates: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Co-ordinates: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Built: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Station class: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Station type: {LTBLUE}{STRING}
diff --git a/src/lang/esperanto.txt b/src/lang/esperanto.txt
index a515912d3fd..bd069f8988f 100644
--- a/src/lang/esperanto.txt
+++ b/src/lang/esperanto.txt
@@ -2167,7 +2167,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Posedant
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Posedanto de fervojo: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Lokaj estroj: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Neniu
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Troviĝo: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Troviĝo: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Kreite: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stacioklaso: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Staciotipo: {LTBLUE}{STRING}
diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt
index c74293382a2..036d5c6d803 100644
--- a/src/lang/estonian.txt
+++ b/src/lang/estonian.txt
@@ -2635,7 +2635,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Trammite
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Raudtee omanik: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Kohalik omavalitsus: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :puudub
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinaadid: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinaadid: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Ehitatud: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Jaama liik: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Jaama rühm: {LTBLUE}{STRING}
diff --git a/src/lang/faroese.txt b/src/lang/faroese.txt
index 6ee2502fbae..5911db23e48 100644
--- a/src/lang/faroese.txt
+++ b/src/lang/faroese.txt
@@ -2305,7 +2305,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Sporvogn
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Jarnbreyta eigari: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Mynduleikar á staðnum: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Eingin
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinatar: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinatar: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Bygt: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Støð klassi: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Støð slag: {LTBLUE}{STRING}
diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt
index 1828c9026e2..cbde444c802 100644
--- a/src/lang/finnish.txt
+++ b/src/lang/finnish.txt
@@ -2622,7 +2622,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Raitioti
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Rautatien omistaja: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Kunta: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Ei mitään
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinaatit: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinaatit: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Rakennettu: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Aseman luokka: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Aseman tyyppi: {LTBLUE}{STRING}
diff --git a/src/lang/french.txt b/src/lang/french.txt
index 226e28b9e17..920d1d47e1f 100644
--- a/src/lang/french.txt
+++ b/src/lang/french.txt
@@ -2626,7 +2626,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Proprié
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Propriétaire des rails{NBSP}: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Municipalité{NBSP}: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Aucune
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordonnées{NBSP}: {LTBLUE}{NUM} × {NUM} × {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordonnées{NBSP}: {LTBLUE}{NUM} × {NUM} × {NUM} × -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Construit le{NBSP}: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Type de station{NBSP}: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Type de station{NBSP}: {LTBLUE}{STRING}
diff --git a/src/lang/gaelic.txt b/src/lang/gaelic.txt
index 0c47be5d263..b14c2aa0394 100644
--- a/src/lang/gaelic.txt
+++ b/src/lang/gaelic.txt
@@ -2795,7 +2795,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Seilbhea
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Seilbheadair na rathaid-iarainn: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Ùghdarras ionadail: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Chan eil gin
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Ionad: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Ionad: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Air a thogail: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Seòrsa an stèisein: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Seòrsa an stèisein: {LTBLUE}{STRING}
diff --git a/src/lang/galician.txt b/src/lang/galician.txt
index f4b6779ed9b..7e34b6027bb 100644
--- a/src/lang/galician.txt
+++ b/src/lang/galician.txt
@@ -2616,7 +2616,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Propieta
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Propietario da vía ferroviaria: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Autoridade local: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Ningunha
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenadas: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenadas: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Construído: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Clase de estación: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Tipo de estación: {LTBLUE}{STRING}
diff --git a/src/lang/german.txt b/src/lang/german.txt
index 26062c4fb16..ac08585f9f2 100644
--- a/src/lang/german.txt
+++ b/src/lang/german.txt
@@ -2595,7 +2595,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Straßen
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Gleiseigentümer: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Gehört zur Gemeinde: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Keine
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinaten: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinaten: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Errichtet am: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stationsklasse: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stationstyp: {LTBLUE}{STRING}
diff --git a/src/lang/greek.txt b/src/lang/greek.txt
index ba8956b94d2..a92bb49d52e 100644
--- a/src/lang/greek.txt
+++ b/src/lang/greek.txt
@@ -2705,7 +2705,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Ιδιο
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Ιδιοκτήτης του σιδηροδρόμου: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Τοπική αρχή: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Καμιά
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Συντεταγμένες: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Συντεταγμένες: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Κατασκευή: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Κατηγορία σταθμού: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Τύπος σταθμού: {LTBLUE}{STRING}
diff --git a/src/lang/hebrew.txt b/src/lang/hebrew.txt
index 2f47bf3d671..05344390458 100644
--- a/src/lang/hebrew.txt
+++ b/src/lang/hebrew.txt
@@ -2588,7 +2588,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}:בעל
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}בעלי מסילת הרכבת: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{LTBLUE}{STRING}{BLACK} :רשות מקומית
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :אין
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}קואורדינטות: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}קואורדינטות: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{LTBLUE}{DATE_LONG}{BLACK} : תאריך בניה
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}{LTBLUE}{STRING}: אופי התחנה
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK} {LTBLUE}{STRING}: סוג התחנה
diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt
index ff9819d2030..5afabd34266 100644
--- a/src/lang/hungarian.txt
+++ b/src/lang/hungarian.txt
@@ -2688,7 +2688,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}A villam
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}A vasúti pálya tulajdonosa: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Helyi önkormányzat: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Nincs
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordináták: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordináták: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Épült: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Állomás osztálya: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Állomás típusa: {LTBLUE}{STRING}
diff --git a/src/lang/icelandic.txt b/src/lang/icelandic.txt
index 02ce0730899..59010cf4e4e 100644
--- a/src/lang/icelandic.txt
+++ b/src/lang/icelandic.txt
@@ -2412,7 +2412,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Eigandi
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Eigandi járnbrautarspors: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Bæjaryfirvöld: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Enginn
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Hnit: {LTBLUE}{NUM}x{NUM}x{NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Hnit: {LTBLUE}{NUM}x{NUM}x{NUM}x-{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Byggt: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Tegund stöðvar: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Tegund stöðvar: {LTBLUE}{STRING}
diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt
index 9ee4f619aa5..87f83c5b419 100644
--- a/src/lang/indonesian.txt
+++ b/src/lang/indonesian.txt
@@ -2586,7 +2586,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Pemilik
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Pemilik Rel Kereta: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Pemkot setempat: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Kosong
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinat: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinat: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Dibuat: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Kelas Stasiun: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Tipe Stasiun: {LTBLUE}{STRING}
diff --git a/src/lang/irish.txt b/src/lang/irish.txt
index 1729a3fcb84..da7e2b394a5 100644
--- a/src/lang/irish.txt
+++ b/src/lang/irish.txt
@@ -2562,7 +2562,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Úinéir
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Úinéir an iarnróid: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Údarás áitiúil: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Ceann ar bith
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Comhordanáidí: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Comhordanáidí: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Tógtha: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Aicme an stáisiúin: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Cineál stáisiúin: {LTBLUE}{STRING}
diff --git a/src/lang/italian.txt b/src/lang/italian.txt
index 7e9d8e30563..6f05fa0083a 100644
--- a/src/lang/italian.txt
+++ b/src/lang/italian.txt
@@ -2654,7 +2654,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Propriet
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Proprietario ferrovia: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Autorità locale: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Nessuna
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordinate: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordinate: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Costruito il: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Tipo stazione: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Tipo stazione: {LTBLUE}{STRING}
diff --git a/src/lang/korean.txt b/src/lang/korean.txt
index 78becf4066b..9439b1588f0 100644
--- a/src/lang/korean.txt
+++ b/src/lang/korean.txt
@@ -2626,7 +2626,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}전찻
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}철도 소유주: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}지역 당국: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :없음
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}좌표: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}좌표: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}건설날짜: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}역 분류: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}역 종류: {LTBLUE}{STRING}
diff --git a/src/lang/latin.txt b/src/lang/latin.txt
index e1b73679cf7..07e66a8c619 100644
--- a/src/lang/latin.txt
+++ b/src/lang/latin.txt
@@ -2797,7 +2797,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Possesso
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Possessor ferriviae: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Auctoritas vicinalis: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Nulla
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordinatae: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordinatae: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Dies struendi: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Classis stationis: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Typus stationis: {LTBLUE}{STRING}
diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt
index bb7ee967d03..007cc4612b4 100644
--- a/src/lang/latvian.txt
+++ b/src/lang/latvian.txt
@@ -2630,7 +2630,7 @@ STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Dzelzce
 STR_LAND_AREA_INFORMATION_RAIL_OWNER.kas                        :{BLACK}Dzelzceļa īpašniece: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Pašvaldība: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Neviena
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinātes: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinātes: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Uzbūvēts: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stacijas klase: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stacijas tips: {LTBLUE}{STRING}
diff --git a/src/lang/lithuanian.txt b/src/lang/lithuanian.txt
index 93008807164..e65f2e99fc6 100644
--- a/src/lang/lithuanian.txt
+++ b/src/lang/lithuanian.txt
@@ -2781,7 +2781,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Tramvaja
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Geležinkelio savininkas: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Vietos valdžia: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Nėra
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinatės: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinatės: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Pastatytas: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stotelės rūšis: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stotelės tipas: {LTBLUE}{STRING}
diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt
index b465025b577..70e87c7c9ad 100644
--- a/src/lang/luxembourgish.txt
+++ b/src/lang/luxembourgish.txt
@@ -2624,7 +2624,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Tramschi
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Schinnebesëtzer: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Gemeng: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Keng
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinaten: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinaten: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Gebaut: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Statiounsklass: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Statiounstyp: {LTBLUE}{STRING}
diff --git a/src/lang/malay.txt b/src/lang/malay.txt
index 8c8cf0746dc..bfd9f71efac 100644
--- a/src/lang/malay.txt
+++ b/src/lang/malay.txt
@@ -2309,7 +2309,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Pemilik
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Pemilik landasan keretapi: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Pihak berkuasa: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Tiada
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinat: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinat: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Dibina: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Kelas stesen: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Jenis stesen: {LTBLUE}{STRING}
diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt
index d282e1e5417..06cf35a9da2 100644
--- a/src/lang/norwegian_bokmal.txt
+++ b/src/lang/norwegian_bokmal.txt
@@ -2617,7 +2617,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Eier av
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Eier av jernbanespor: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Bystyret: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Ingen
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinater: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinater: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Bygget: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stasjonstype: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stasjonstype: {LTBLUE}{STRING}
diff --git a/src/lang/norwegian_nynorsk.txt b/src/lang/norwegian_nynorsk.txt
index 5eb0d5b8a7b..f46f2ff9eaf 100644
--- a/src/lang/norwegian_nynorsk.txt
+++ b/src/lang/norwegian_nynorsk.txt
@@ -2485,7 +2485,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Trikkesp
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Jernbaneskjene-eigar: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Bystyret: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Ingen
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinatar: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinatar: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Byggd: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stasjonsklasse: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stasjontype: {LTBLUE}{STRING}
diff --git a/src/lang/polish.txt b/src/lang/polish.txt
index bcbfd249671..bdb0ab0a245 100644
--- a/src/lang/polish.txt
+++ b/src/lang/polish.txt
@@ -3005,7 +3005,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Właści
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Wlaściciel linii kolejowej: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Lokalne władze: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Brak
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Współrzędne: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Współrzędne: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Zbudowano: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Rodzaj stacji: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Typ stacji: {LTBLUE}{STRING}
diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt
index d39767aa492..232bba225ab 100644
--- a/src/lang/portuguese.txt
+++ b/src/lang/portuguese.txt
@@ -2611,7 +2611,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Dono da
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Dono da linha férrea: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Autoridade local: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Nenhum
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenadas: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenadas: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Construído: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Tipo de estação: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Tipo de estação: {LTBLUE}{STRING}
diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt
index 2842dd4fecb..78d5aed7f34 100644
--- a/src/lang/romanian.txt
+++ b/src/lang/romanian.txt
@@ -2544,7 +2544,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Propriet
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Proprietar al căii ferate: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Autoritatea locală: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Nici una
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordonate: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordonate: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Data construcţiei: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Clasa staţiei: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Tip staţie: {LTBLUE}{STRING}
diff --git a/src/lang/russian.txt b/src/lang/russian.txt
index 266fdad22fc..ea9e37b4219 100644
--- a/src/lang/russian.txt
+++ b/src/lang/russian.txt
@@ -588,6 +588,18 @@ STR_LANDSCAPING_MENU_PLANT_TREES                                :Высадка
 STR_LANDSCAPING_MENU_PLACE_SIGN                                 :Поставить метку
 ############ range ends here
 
+############ range for underground menu starts
+STR_LANDSCAPING_MENU_UNDERGROUND                                :Спец. конструкции
+STR_LANDSCAPING_MENU_LAYER_1                                    :Поверхность
+STR_LANDSCAPING_MENU_LAYER_2                                    :Подземелье (-1)
+STR_LANDSCAPING_MENU_LAYER_3                                    :Подземелье (-2)
+STR_LANDSCAPING_MENU_LAYER_4                                    :Подземелье (-3)
+STR_LANDSCAPING_MENU_LAYER_5                                    :Подземелье (-4)
+STR_LANDSCAPING_MENU_LAYER_6                                    :Подземелье (-5)
+STR_LANDSCAPING_MENU_LAYER_7                                    :Подземелье (-6)
+STR_LANDSCAPING_MENU_LAYER_8                                    :Подземелье (-7)
+############ range ends here
+
 ############ range for music menu starts
 STR_TOOLBAR_SOUND_MUSIC                                         :Звук/музыка
 ############ range ends here
@@ -2805,7 +2817,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Влад
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Владелец ж/д пути: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Администрация: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Нет
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Координаты: {LTBLUE}{NUM} × {NUM} × {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Координаты: {LTBLUE}{NUM} × {NUM} × {NUM} × -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Построено: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Класс станции: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Тип станции: {LTBLUE}{STRING}
@@ -5378,3 +5390,35 @@ STR_PLANE                                                       :{BLACK}{PLANE}
 STR_SHIP                                                        :{BLACK}{SHIP}
 
 STR_TOOLBAR_RAILTYPE_VELOCITY                                   :{STRING} ({VELOCITY})
+
+#	underground
+
+#	error
+STR_ERROR_UNDERGROUND_CAN_T_BUILD_UNDER_GROUND			    	:{WHITE}Не может строиться под землей
+STR_ERROR_UNDERGROUND_CAN_T_BUILD_OVER_GROUND					:{WHITE}Не может строиться на поверхности
+STR_ERROR_UNDERGROUND_CAN_T_TERRAFORM							:{WHITE}Изменение ландшафта недоступно
+STR_ERROR_UNDERGROUND_CAN_T_BUILD_PART                          :{WHITE}Нельзя построить эскалатор...
+STR_ERROR_UNDERGROUND_CAN_T_BUILD_TOP_PART                      :{WHITE}Нельзя построить верхнюю часть эскалатора...
+STR_ERROR_UNDERGROUND_CAN_T_BUILD_BOTTOM_PART                   :{WHITE}Нельзя построить нижнюю часть эскалатора...
+
+#	menus
+STR_UNDERGROUND_LAYER_COUNT										:{BLACK}Количество слоев
+STR_UNDERGROUND_BUILD											:{WHITE}Подземелье
+
+#	underground land types
+STR_UNDERGROUND_FLAT											:Пещера
+STR_UNDERGROUND_SOLID											:Грунт
+STR_UNDERGROUND_ROCKS											:Скалы
+STR_UNDERGROUND_HEAVY_ROCKS										:Твердые породы
+
+#	underground special build types
+STR_UNDERGROUND_ESCALATOR										:Эскалатор
+STR_UNDERGROUND_CONNECT											:Соединение
+STR_UNDERGROUND_PIPE											:Трубы
+
+#	underground tool tip
+STR_UNDERGROUND_TOOLTIP_ESCALATOR								:{BLACK}Постройка эскалатора (связь подземной станции с поверхностью)
+STR_UNDERGROUND_TOOLTIP_CONNECT									:{BLACK}Постройка подъема (подземные рельсы выходят наружу)
+STR_UNDERGROUND_TOOLTIP_PIPE									:{BLACK}Трубы (хм... что-то...)
+
+#	end underground string
diff --git a/src/lang/serbian.txt b/src/lang/serbian.txt
index 839269d696f..dd13f5d23bd 100644
--- a/src/lang/serbian.txt
+++ b/src/lang/serbian.txt
@@ -2770,7 +2770,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Vlasnik
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Vlasnik železničke pruge: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Lokalna vlast: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Nema
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinate: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinate: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Sagrađeno: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Klasa stanice: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Vrsta stanice: {LTBLUE}{STRING}
diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt
index d3aa2d98b94..e966953a5f8 100644
--- a/src/lang/simplified_chinese.txt
+++ b/src/lang/simplified_chinese.txt
@@ -2625,7 +2625,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}有轨
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}铁路归属:{LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}地方政府:{LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :没有
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}坐标: {LTBLUE}{NUM} × {NUM} × {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}坐标: {LTBLUE}{NUM} × {NUM} × {NUM} × -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}建造时间:{LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}车站分类: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}车站类型: {LTBLUE}{STRING}
diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt
index 20ab973b841..8cdcd18de54 100644
--- a/src/lang/slovak.txt
+++ b/src/lang/slovak.txt
@@ -2630,7 +2630,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Vlastní
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Vlastník železnice: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Miestna správa: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Neznáme
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Súradnice: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Súradnice: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Postavene: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Trieda stanice: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Typ stanice: {LTBLUE}{STRING}
diff --git a/src/lang/slovenian.txt b/src/lang/slovenian.txt
index f07f071ff8c..bcb8cb21d6a 100644
--- a/src/lang/slovenian.txt
+++ b/src/lang/slovenian.txt
@@ -2718,7 +2718,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Lastnik
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Lastnik železnice: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Lokalna oblast: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Brez
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinate: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinate: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Zgrajeno: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Razred postaje: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Vrsta postaje: {LTBLUE}{STRING}
diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt
index 3ea15362cb1..176e655d047 100644
--- a/src/lang/spanish.txt
+++ b/src/lang/spanish.txt
@@ -2614,7 +2614,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Propieta
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Propietario del ferrocarril: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Autoridad local: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Ninguna
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenadas: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenadas: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Construido: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Clase de estación: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Tipo de estación: {LTBLUE}{STRING}
diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt
index 5571c32f5f0..7efa57540f8 100644
--- a/src/lang/spanish_MX.txt
+++ b/src/lang/spanish_MX.txt
@@ -2626,7 +2626,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Propieta
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Propietario del ferrocarril: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Ayuntamiento: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Ninguno
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenadas: {LTBLUE}{NUM}×{NUM}×{NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Coordenadas: {LTBLUE}{NUM}×{NUM}×{NUM}×-{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Construido: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Clase de estación: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Tipo de estación: {LTBLUE}{STRING}
diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt
index 909ce0e4abd..b6f066b6b4d 100644
--- a/src/lang/swedish.txt
+++ b/src/lang/swedish.txt
@@ -2625,7 +2625,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Spårvä
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Järnvägens ägare: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Lokala myndigheter: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Ingen
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinater: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinater: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Byggt: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Stationsklass: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Stationstyp: {LTBLUE}{STRING}
diff --git a/src/lang/tamil.txt b/src/lang/tamil.txt
index 0727649df87..9de395f852f 100644
--- a/src/lang/tamil.txt
+++ b/src/lang/tamil.txt
@@ -2301,7 +2301,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}ட்
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}இரயில்வே உரிமையாளர்: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}நகராட்சி: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :ஒன்றுமில்லை
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}அச்சுத் தூரங்கள்: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}அச்சுத் தூரங்கள்: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}கட்டப்பட்டது: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}நிலையத்தின் பிரிவு: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}நிலையத்தின் வகை: {LTBLUE}{STRING}
diff --git a/src/lang/thai.txt b/src/lang/thai.txt
index 258be30a15b..917bd2e6b55 100644
--- a/src/lang/thai.txt
+++ b/src/lang/thai.txt
@@ -2511,7 +2511,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}ผู
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}ผู้ครอบครองทางรถไฟ: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}ขึ้นตรงกับผู้ดูแลในท้องถิ่น: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :ไม่มี
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}ตำแหน่ง: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}ตำแหน่ง: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}สร้างเมื่อ: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}ประเภทของสถานี: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}รูปแบบของสถานี: {LTBLUE}{STRING}
diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt
index d530adbad3c..7eeeab4c985 100644
--- a/src/lang/traditional_chinese.txt
+++ b/src/lang/traditional_chinese.txt
@@ -2565,7 +2565,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}電車
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}鐵路所有者:{LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}地方政府:{LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :無
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}座標:{LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}座標:{LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}建於:{LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}車站風格:{LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}車站種類:{LTBLUE}{STRING}
diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt
index 8193f2970e3..a9387934118 100644
--- a/src/lang/turkish.txt
+++ b/src/lang/turkish.txt
@@ -2591,7 +2591,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Tramvay
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Demiryolu sahibi: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Belediyesi: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Hiçbiri
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinatlar: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Koordinatlar: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Yapım: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}İstasyon sınıfı: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}İstasyon türü: {LTBLUE}{STRING}
diff --git a/src/lang/ukrainian.txt b/src/lang/ukrainian.txt
index caab8a01693..1963feb70d4 100644
--- a/src/lang/ukrainian.txt
+++ b/src/lang/ukrainian.txt
@@ -2746,7 +2746,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Влас
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Власник залізниці: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Місцева влада: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Немає
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Координати: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Координати: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Рік випуску: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Клас станції: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Тип станції: {LTBLUE}{STRING}
diff --git a/src/lang/unfinished/persian.txt b/src/lang/unfinished/persian.txt
index 2865d4e4614..69e48496e9c 100644
--- a/src/lang/unfinished/persian.txt
+++ b/src/lang/unfinished/persian.txt
@@ -2266,7 +2266,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}مالک
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}مالک ریل راه آهن: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}فرماندار محلی: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :هیچکدام
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}مختصات: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}مختصات: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}ساخته شده در: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}کلاس ایستگاه: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}نوع ایستگاه: {LTBLUE}{STRING}
diff --git a/src/lang/vietnamese.txt b/src/lang/vietnamese.txt
index 1ce6b766f5b..7465f508f10 100644
--- a/src/lang/vietnamese.txt
+++ b/src/lang/vietnamese.txt
@@ -2615,7 +2615,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Chủ đ
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Chủ đường ray: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Thuộc về địa phương: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Không
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Toạ độ: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Toạ độ: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Xây lúc: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Loại ga,bến: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Kiểu ga,bến: {LTBLUE}{STRING}
diff --git a/src/lang/welsh.txt b/src/lang/welsh.txt
index cd5a116d350..29d821c355a 100644
--- a/src/lang/welsh.txt
+++ b/src/lang/welsh.txt
@@ -2570,7 +2570,7 @@ STR_LAND_AREA_INFORMATION_TRAM_OWNER                            :{BLACK}Perchenn
 STR_LAND_AREA_INFORMATION_RAIL_OWNER                            :{BLACK}Perchennog rheilffordd: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY                       :{BLACK}Awdurdod Lleol: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE                  :Dim
-STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Cyfeirnodau: {LTBLUE}{NUM} x {NUM} x {NUM} ({STRING})
+STR_LAND_AREA_INFORMATION_LANDINFO_COORDS                       :{BLACK}Cyfeirnodau: {LTBLUE}{NUM} x {NUM} x {NUM} x -{NUM} ({STRING})
 STR_LAND_AREA_INFORMATION_BUILD_DATE                            :{BLACK}Adeiladwyd: {LTBLUE}{DATE_LONG}
 STR_LAND_AREA_INFORMATION_STATION_CLASS                         :{BLACK}Dosbarth gorsaf: {LTBLUE}{STRING}
 STR_LAND_AREA_INFORMATION_STATION_TYPE                          :{BLACK}Math gorsaf: {LTBLUE}{STRING}
diff --git a/src/layer.cpp b/src/layer.cpp
new file mode 100644
index 00000000000..aab234e53d2
--- /dev/null
+++ b/src/layer.cpp
@@ -0,0 +1,136 @@
+/* $Id: map.cpp 23740 2012-01-03 21:32:51Z  $ */
+/*
+
+��� ������, ��� ����������� ����������� ���� � ���� ����������
+(����������, �����, ���.)
+
+
+������� ������� ���� �������� �������� ���:
+*-----------*
+|           |
+|           |
+|           |
+*-----------*
+
+�������� ������� ��� �� ���������� �����:
+*---*---*---*
+|   |   |   |
+|   |   |   |
+|   |   |   |
+*---*---*---*
+
+�������� ������� ����� � ������������ ��������:
+*---*
+| *---*
+| | *---*
+| | |   |
+* | |   |
+  * |   |
+    *---*
+
+����� ������� ���� ������� ����� �� ��������� 3� ������������.
+
+��� �������� ��� ����� ������� ������ �� ��� Y (������� ����������� ��� X)
+������� ���������� �� 1, 2, 4, ��� 8 ��������.
+
+�������� ���� ������� ���� 64�64, � 4-�� ������:
+��������� ����� 64�256, ���������������, ���:
+
+	                  X        Y
+	������� ����    0--63    0--63
+	������ ����	   	0--63    64--127
+	������ ����	    0--63    128--191
+	��������� ����  0--63    192--255
+
+
+������� �����
+	MapSizeX � (MapSizeY)
+
+������������� � ���� �����
+	LayerSizeX x (LayerSizeY x LayerCount)
+
+����� ������� ������� ���������� "��������" ������������
+
+	MapX, MapY, MapZ
+
+��������� � ���������� ������ "3�" ������������
+
+	//	���������
+	LayerCount = ����� ��������... (1, ��� 2, ��� 4, ���.)
+	LayerSizeZ = ����� ���� �� ��������� (�������� 1)
+
+	//	�������
+	MapSizeX == LayerSizeX
+	MapSizeY == LayerSizeY * LayerCount
+
+	//	������ ���������
+	LayerIndex = MapY / LayerSizeY
+
+	WorldX = MapX
+	WorldY = MapY - LayerIndex*LayerSizeY
+	WorldZ = MapZ + LayerIndex*LayerSizeZ
+*/
+
+/** @file map.cpp Base functions related to the map and distances on them. */
+
+#include "stdafx.h"
+#include "debug.h"
+#include "core/alloc_func.hpp"
+#include "void_map.h"
+#include "layer_func.h"
+#include "layer_type.h"
+#include "landscape.h"
+
+#if defined(_MSC_VER)
+/* Why the hell is that not in all MSVC headers?? */
+extern "C" _CRTIMP void __cdecl _assert(void *, void *, unsigned);
+#endif
+
+uint _layer_size_x;    ///< Size of the map along the X
+uint _layer_size_y;    ///< Size of the map along the Y
+uint _layer_count;     ///< The number of tiles on the map
+uint _layer_count_log;
+uint _layer_size;      ///< Layer size (sizeX * sizeY)
+
+void InstallLayerSystem(uint size_x, uint size_y, uint layer_count)
+{
+	if (!IsInsideMM(layer_count, MIN_LAYER_COUNT, MAX_LAYER_COUNT+1))
+		error("invalid layer count");
+
+	_layer_size_x = size_x;
+	_layer_size_y = size_y;
+	_layer_size = size_x * size_y;
+	_layer_count = layer_count;
+	_layer_count_log = FindFirstBit(layer_count);
+}
+
+void FixUndergroundHeights()
+{
+	uint width = MapSizeX();
+	uint height = MapSizeY();
+
+	/* Layer correct */
+	for (uint row = 0; (uint)row < height; row++) {
+
+		/*	������� ����� ������	*/
+		if (!(row % LayerSizeY()))
+			for (uint x = 0; x < width; x++) MakeVoid(width * row + x);
+
+		for (uint col = 0; (uint)col < width; col++) {
+			uint tile = TileXY(row, col);
+			if (IsUnderground(tile))
+				SetTileHeight(tile, 0);
+		}
+	}
+}
+
+uint8 calculateLayer(const Viewport *vp)
+{
+	//	������� ViewportDoDraw ���������� ��������� ��� � ������� �����������
+	//	����� �� ����� ������ ���� ����.
+	//	��������� �� �������.
+
+	Point pt = InverseRemapCoords(vp->virtual_left+(vp->virtual_width >> 1),vp->virtual_top+(vp->virtual_height >> 1));
+	TileIndex center = TileVirtXY(pt.x, pt.y);
+	return LayerIndex(center);
+}
diff --git a/src/layer_func.h b/src/layer_func.h
new file mode 100644
index 00000000000..05022163a2d
--- /dev/null
+++ b/src/layer_func.h
@@ -0,0 +1,102 @@
+/* $Id: layer_func.h 2012-09-07 18:11:11 constructor $ */
+
+/*
+*	�������� �������� ��. � layer.cpp
+*/
+
+/** @file layer_func.h Functions related to layer in maps. */
+
+#ifndef LAYER_FUNC_H
+#define LAYER_FUNC_H
+
+#include "map_func.h"
+#include "viewport_type.h"
+
+/*
+*
+*	������������� "����������"
+*	���������� ����� "1" ����������� ���� ��� "����������"
+*
+*/
+void InstallLayerSystem(uint size_x, uint size_y, uint layer_count);
+
+/*	������������� "���������" �����
+*	(� ������� ���� ����� ������ ������ -- � �������� �������) */
+void FixUndergroundHeights();
+
+#define UNDERGROUND_COST_MULTIPLIER(tile)  (1 + 100 * (TileHeight(TopTile(tile))-TileHeight(tile)-LayerIndex(tile)))
+
+#define FOR_ALL_LAYERS(var) for (uint var = 0; var < LayerCount(); var++)
+
+/**
+ * Get the X component of a tile
+ * @param tile the tile to get the X component of
+ * @return the X component
+ */
+static inline uint LayerX(TileIndex tile)
+{
+	return tile & LayerMaxX();
+}
+
+/**
+ * Get the Y component of a tile
+ * @param tile the tile to get the Y component of
+ * @return the Y component
+ */
+static inline uint LayerY(TileIndex tile)
+{
+	return (tile >> MapLogX()) & LayerMaxY();
+}
+
+static inline uint LayerIndex(TileIndex tile)
+{
+	return (tile >> MapLogX()) / LayerSizeY();
+}
+
+static inline bool IsUnderground(TileIndex tile)
+{
+	return LayerIndex(tile) != 0;
+}
+
+/**
+*	������ ����.
+*	����� ��������� � ������, ����� �������� ������ ����
+*/
+static inline uint LayerSize()
+{
+	extern uint _layer_size;
+	return _layer_size;
+}
+
+/**
+ * ���� ������ ����������� ��� ������ (����� ������� ������)
+ * @param tile the tile to get the Y component of
+ * @return the Y component
+ */
+static inline uint TopTile(TileIndex tile)
+{
+	uint layer = LayerIndex(tile);
+	return (tile - layer * LayerSize());
+}
+
+/*	���������� ������� �� �������� ����� ������	*/
+static inline bool IsTopTile(TileIndex tile)
+{
+	return (tile < LayerSize());
+}
+
+/*	���� ������ ��� ������. (��� ����� ������� ������ ������??)
+*/
+static inline uint UpTile(TileIndex tile)
+{
+	return TILE_MASK(tile - LayerSize());
+}
+
+/*	���� ������ ��� ������. (��� ����� ������ ������ �������??)
+*/
+static inline uint DownTile(TileIndex tile)
+{
+	return TILE_MASK(tile + LayerSize());
+}
+
+#endif /* LAYER_FUNC_H */
diff --git a/src/layer_gui.h b/src/layer_gui.h
new file mode 100644
index 00000000000..7b791b7e9f3
--- /dev/null
+++ b/src/layer_gui.h
@@ -0,0 +1,17 @@
+/* $Id: layer_func.h 2012-09-07 18:11:11 constructor $ */
+
+/*
+*	�������� �������� ��. � layer.cpp
+*/
+
+/** @file layer_gui.h Functions for visualisation map with support layers */
+
+#ifndef LAYER_GUI_H
+#define LAYER_GUI_H
+
+#include "layer_func.h"
+#include "viewport_type.h"
+
+uint8 calculateLayer(const Viewport *vp);
+
+#endif /* LAYER_GUI_H */
diff --git a/src/layer_type.h b/src/layer_type.h
new file mode 100644
index 00000000000..53eafdde639
--- /dev/null
+++ b/src/layer_type.h
@@ -0,0 +1,22 @@
+/* $Id: layer_type.h 21493 2012-09-11 2:21:53Z constructor $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file layer_type.h Types related to maps. */
+
+#ifndef LAYER_TYPE_H
+#define LAYER_TYPE_H
+
+/** Minimal and maximal layer counts */
+static const uint MIN_LAYER_COUNT_BITS = 0;							///< Minimal size of map is equal to 2 ^ MIN_LAYER_SIZE_BITS
+static const uint MAX_LAYER_COUNT_BITS = 3;							///< Maximal size of map is equal to 2 ^ MAX_LAYER_SIZE_BITS
+static const uint MIN_LAYER_COUNT      = 1 << MIN_LAYER_COUNT_BITS;	///< Minimal layer count = 1
+static const uint MAX_LAYER_COUNT      = 1 << MAX_LAYER_COUNT_BITS;	///< Maximal layer count = 8
+
+
+#endif /* LAYER_TYPE_H */
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index 5343e2ed11f..317b360b244 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -31,6 +31,9 @@
 #include "tilehighlight_func.h"
 #include "hotkeys.h"
 #include "guitimer_func.h"
+#include "gfx_func.h"
+#include "layer_gui.h"
+#include "landscape.h"
 
 #include "saveload/saveload.h"
 
@@ -102,7 +105,7 @@ bool HandlePlacePushButton(Window *w, int widget, CursorID cursor, HighLightStyl
 	if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
 	w->SetDirty();
 
-	if (w->IsWidgetLowered(widget)) {
+	if (w->IsWidgetLowered(widget) && mode == _thd.place_mode) {
 		ResetObjectToPlace();
 		return false;
 	}
@@ -197,6 +200,22 @@ void ZoomInOrOutToCursorWindow(bool in, Window *w)
 	}
 }
 
+void LayerUpOrDownToCursorWindow(bool in, Window *w)
+{
+	assert(w != NULL);
+
+	if (_game_mode != GM_MENU) {
+		int layer = calculateLayer(w->viewport) + (in ? -1 : 1);
+		if ((layer < 0) || (layer >= LayerCount())) return;
+
+		Point pt = RemapCoords(0, (in ? -1 : 1) * LayerSizeY() * TILE_SIZE, 0);
+		w->viewport->dest_scrollpos_x += pt.x;
+		w->viewport->dest_scrollpos_y += pt.y;
+		w->InvalidateData();
+
+	}
+}
+
 void FixTitleGameZoom()
 {
 	if (_game_mode != GM_MENU) return;
@@ -444,7 +463,11 @@ struct MainWindow : Window
 	void OnMouseWheel(int wheel) override
 	{
 		if (_settings_client.gui.scrollwheel_scrolling != 2) {
-			ZoomInOrOutToCursorWindow(wheel < 0, this);
+			if (_ctrl_pressed) {
+				LayerUpOrDownToCursorWindow(wheel < 0, this);
+			} else {
+				ZoomInOrOutToCursorWindow(wheel < 0, this);
+			}
 		}
 	}
 
diff --git a/src/map.cpp b/src/map.cpp
index 679c445ee1d..9ad1077c9b3 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -11,6 +11,7 @@
 #include "debug.h"
 #include "core/alloc_func.hpp"
 #include "water_map.h"
+#include "layer_func.h"
 #include "string_func.h"
 
 #include "safeguards.h"
@@ -36,7 +37,7 @@ TileExtended *_me = nullptr; ///< Extended Tiles of the map
  * @param size_x the width of the map along the NE/SW edge
  * @param size_y the 'height' of the map along the SE/NW edge
  */
-void AllocateMap(uint size_x, uint size_y)
+void AllocateMap(uint size_x, uint size_y, uint layer_count)
 {
 	/* Make sure that the map size is within the limits and that
 	 * size of both axes is a power of 2. */
@@ -47,6 +48,10 @@ void AllocateMap(uint size_x, uint size_y)
 		error("Invalid map size");
 	}
 
+	/*	��������� ���� ����� �����, �������� �� �����	*/
+	InstallLayerSystem(size_x, size_y, layer_count);
+	size_y *= layer_count;
+
 	DEBUG(map, 1, "Allocating map of size %dx%d", size_x, size_y);
 
 	_map_log_x = FindFirstBit(size_x);
@@ -268,6 +273,7 @@ bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, v
 		/* If tile test is not successful, get one tile up,
 		 * ready for a test in first circle around center tile */
 		*tile = TileAddByDir(*tile, DIR_N);
+		if (size / 2 == 0) return false;
 		return CircularTileSearch(tile, size / 2, 1, 1, proc, user_data);
 	} else {
 		return CircularTileSearch(tile, size / 2, 0, 0, proc, user_data);
diff --git a/src/map_func.h b/src/map_func.h
index b02ba577737..f0c3edc414a 100644
--- a/src/map_func.h
+++ b/src/map_func.h
@@ -41,7 +41,7 @@ extern Tile *_m;
  */
 extern TileExtended *_me;
 
-void AllocateMap(uint size_x, uint size_y);
+void AllocateMap(uint size_x, uint size_y, uint layer_count);
 
 /**
  * Logarithm of the map size along the X side.
@@ -113,6 +113,64 @@ static inline uint MapMaxY()
 	return MapSizeY() - 1;
 }
 
+/**
+ * Get the size of the layer along the X
+ * @return the number of tiles along the X of the layer
+ */
+static inline uint LayerSizeX()
+{
+	extern uint _map_size_x;
+	return _map_size_x;
+}
+
+/**
+ * Get the size of the layer along the Y
+ * @return the number of tiles along the Y of the layer
+ */
+static inline uint LayerSizeY()
+{
+	extern uint _layer_size_y;
+	return _layer_size_y;
+}
+
+/**
+ * Gets the maximum X coordinate within the map, including MP_VOID
+ * @return the maximum X coordinate
+ */
+static inline uint LayerMaxX()
+{
+	return LayerSizeX() - 1;
+}
+
+/**
+ * Gets the maximum Y coordinate within the map, including MP_VOID
+ * @return the maximum Y coordinate
+ */
+static inline uint LayerMaxY()
+{
+	return LayerSizeY() - 1;
+}
+
+/**
+ * Get the layer counts
+ * @return the number of layers
+ */
+static inline uint LayerCount()
+{
+	extern uint _layer_count;
+	return _layer_count;
+}
+
+/**
+ * Get the layer counts
+ * @return the number of layers
+ */
+static inline uint LayerCountLog()
+{
+	extern uint _layer_count_log;
+	return _layer_count_log;
+}
+
 /**
  * Scales the given value by the map size, where the given value is
  * for a 256 by 256 map.
@@ -123,7 +181,7 @@ static inline uint ScaleByMapSize(uint n)
 {
 	/* Subtract 12 from shift in order to prevent integer overflow
 	 * for large values of n. It's safe since the min mapsize is 64x64. */
-	return CeilDiv(n << (MapLogX() + MapLogY() - 12), 1 << 4);
+	return CeilDiv(n << (MapLogX() + MapLogY() - LayerCountLog() - 12), 1 << 4);
 }
 
 
diff --git a/src/misc.cpp b/src/misc.cpp
index dcb04fa0266..0e282163005 100644
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -8,6 +8,7 @@
 /** @file misc.cpp Misc functions that shouldn't be here. */
 
 #include "stdafx.h"
+#include "layer_func.h"
 #include "landscape.h"
 #include "news_func.h"
 #include "ai/ai.hpp"
@@ -61,7 +62,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
 	 * related to the new game we're about to start/load. */
 	UnInitWindowSystem();
 
-	AllocateMap(size_x, size_y);
+	AllocateMap(size_x, size_y, 1 << _settings_game.game_creation.layers);
 
 	_pause_mode = PM_UNPAUSED;
 	_fast_forward = 0;
diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp
index ff2fc3a23c4..74b59d294b1 100644
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -216,10 +216,11 @@ public:
 		/* Location */
 		char tmp[16];
 		seprintf(tmp, lastof(tmp), "0x%.4X", tile);
-		SetDParam(0, TileX(tile));
-		SetDParam(1, TileY(tile));
+		SetDParam(0, LayerX(tile));
+		SetDParam(1, LayerY(tile));
 		SetDParam(2, GetTileZ(tile));
-		SetDParamStr(3, tmp);
+		SetDParam(3, LayerIndex(tile));
+		SetDParamStr(4, tmp);
 		GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_LANDINFO_COORDS, lastof(this->landinfo_data[line_nr]));
 		line_nr++;
 
diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp
index 3fb61d647e5..3b08cc637d8 100644
--- a/src/object_cmd.cpp
+++ b/src/object_cmd.cpp
@@ -695,7 +695,7 @@ static bool TryBuildLightHouse()
  */
 static bool TryBuildTransmitter()
 {
-	TileIndex tile = RandomTile();
+	TileIndex tile = TopTile(RandomTile());
 	int h;
 	if (IsTileType(tile, MP_CLEAR) && IsTileFlat(tile, &h) && h >= 4 && !IsBridgeAbove(tile)) {
 		TileIndex t = tile;
@@ -759,7 +759,7 @@ void GenerateObjects()
 
 				default:
 					uint8 view = RandomRange(spec->views);
-					if (CmdBuildObject(RandomTile(), DC_EXEC | DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, i, view, nullptr).Succeeded()) amount--;
+					if (CmdBuildObject(TopTile(RandomTile()), DC_EXEC | DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, i, view, nullptr).Succeeded()) amount--;
 					break;
 			}
 		}
diff --git a/src/rail.h b/src/rail.h
index d9121d545a8..ee27f6e1793 100644
--- a/src/rail.h
+++ b/src/rail.h
@@ -158,7 +158,7 @@ public:
 		SpriteID signals[SIGTYPE_END][2][2]; ///< signal GUI sprites (type, variant, state)
 	} gui_sprites;
 
-	struct {
+	struct Cursor {
 		CursorID rail_ns;    ///< Cursor for building rail in N-S direction
 		CursorID rail_swne;  ///< Cursor for building rail in X direction
 		CursorID rail_ew;    ///< Cursor for building rail in E-W direction
diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp
index 162fe97799a..33cf2b245cb 100644
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -533,12 +533,12 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u
 
 					uint num_new_road_pieces = (road != ROAD_NONE) ? 2 - CountBits(road) : 0;
 					if (num_new_road_pieces > 0) {
-						cost.AddCost(num_new_road_pieces * RoadBuildCost(roadtype_road));
+						cost.AddCost(num_new_road_pieces * RoadBuildCost(roadtype_road) * UNDERGROUND_COST_MULTIPLIER(tile));
 					}
 
 					uint num_new_tram_pieces = (tram != ROAD_NONE) ? 2 - CountBits(tram) : 0;
 					if (num_new_tram_pieces > 0) {
-						cost.AddCost(num_new_tram_pieces * RoadBuildCost(roadtype_tram));
+						cost.AddCost(num_new_tram_pieces * RoadBuildCost(roadtype_tram) * UNDERGROUND_COST_MULTIPLIER(tile));
 					}
 
 					if (flags & DC_EXEC) {
@@ -601,7 +601,7 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u
 		YapfNotifyTrackLayoutChange(tile, track);
 	}
 
-	cost.AddCost(RailBuildCost(railtype));
+	cost.AddCost(RailBuildCost(railtype) * UNDERGROUND_COST_MULTIPLIER(tile));
 	return cost;
 }
 
@@ -645,7 +645,7 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1,
 				if (ret.Failed()) return ret;
 			}
 
-			cost.AddCost(RailClearCost(GetRailType(tile)));
+			cost.AddCost(RailClearCost(GetRailType(tile)) * UNDERGROUND_COST_MULTIPLIER(tile));
 
 			if (flags & DC_EXEC) {
 				if (HasReservedTracks(tile, trackbit)) {
@@ -679,7 +679,7 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1,
 			if ((present & trackbit) == 0) return_cmd_error(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK);
 			if (present == (TRACK_BIT_X | TRACK_BIT_Y)) crossing = true;
 
-			cost.AddCost(RailClearCost(GetRailType(tile)));
+			cost.AddCost(RailClearCost(GetRailType(tile)) * UNDERGROUND_COST_MULTIPLIER(tile));
 
 			/* Charge extra to remove signals on the track, if they are there */
 			if (HasSignalOnTrack(tile, track)) {
@@ -994,7 +994,7 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, u
 		if (!_settings_game.construction.build_on_slopes || !CanBuildDepotByTileh(dir, tileh)) {
 			return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
 		}
-		cost.AddCost(_price[PR_BUILD_FOUNDATION]);
+		cost.AddCost(_price[PR_BUILD_FOUNDATION] * UNDERGROUND_COST_MULTIPLIER(tile));
 	}
 
 	cost.AddCost(DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR));
@@ -1019,8 +1019,8 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, u
 		YapfNotifyTrackLayoutChange(tile, DiagDirToDiagTrack(dir));
 	}
 
-	cost.AddCost(_price[PR_BUILD_DEPOT_TRAIN]);
-	cost.AddCost(RailBuildCost(railtype));
+	cost.AddCost(_price[PR_BUILD_DEPOT_TRAIN] * UNDERGROUND_COST_MULTIPLIER(tile));
+	cost.AddCost(RailBuildCost(railtype) * UNDERGROUND_COST_MULTIPLIER(tile));
 	return cost;
 }
 
@@ -1672,7 +1672,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
 							InvalidateWindowData(WC_BUILD_VEHICLE, tile);
 						}
 						found_convertible_track = true;
-						cost.AddCost(RailConvertCost(type, totype));
+						cost.AddCost(RailConvertCost(type, totype) * UNDERGROUND_COST_MULTIPLIER(tile));
 						break;
 
 					default: // RAIL_TILE_NORMAL, RAIL_TILE_SIGNALS
@@ -1684,7 +1684,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
 							}
 						}
 						found_convertible_track = true;
-						cost.AddCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile)));
+						cost.AddCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile)) * UNDERGROUND_COST_MULTIPLIER(tile));
 						break;
 				}
 				break;
@@ -1747,7 +1747,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
 				}
 
 				found_convertible_track = true;
-				cost.AddCost((GetTunnelBridgeLength(tile, endtile) + 2) * RailConvertCost(type, totype));
+				cost.AddCost((GetTunnelBridgeLength(tile, endtile) + 2) * RailConvertCost(type, totype) * UNDERGROUND_COST_MULTIPLIER(tile));
 				break;
 			}
 
@@ -1758,7 +1758,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
 				}
 
 				found_convertible_track = true;
-				cost.AddCost(RailConvertCost(type, totype));
+				cost.AddCost(RailConvertCost(type, totype) * UNDERGROUND_COST_MULTIPLIER(tile));
 				break;
 		}
 
diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp
index b8aee88d60b..b3921712eac 100644
--- a/src/road_cmd.cpp
+++ b/src/road_cmd.cpp
@@ -402,7 +402,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits piec
 			}
 		} else {
 			assert(IsDriveThroughStopTile(tile));
-			cost.AddCost(RoadClearCost(existing_rt) * 2);
+			cost.AddCost(RoadClearCost(existing_rt) * 2 * UNDERGROUND_COST_MULTIPLIER(tile));
 			if (flags & DC_EXEC) {
 				/* A full diagonal road tile has two road bits. */
 				UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2);
@@ -883,7 +883,7 @@ do_clear:;
 			/* Count pieces */
 			CountBits(pieces);
 
-	cost.AddCost(num_pieces * RoadBuildCost(rt));
+	cost.AddCost(num_pieces * RoadBuildCost(rt) * UNDERGROUND_COST_MULTIPLIER(tile));
 
 	if (flags & DC_EXEC) {
 		switch (GetTileType(tile)) {
@@ -1197,7 +1197,7 @@ CommandCost CmdBuildRoadDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
 		MarkTileDirtyByTile(tile);
 		MakeDefaultName(dep);
 	}
-	cost.AddCost(_price[PR_BUILD_DEPOT_ROAD]);
+	cost.AddCost(_price[PR_BUILD_DEPOT_ROAD] * UNDERGROUND_COST_MULTIPLIER(tile));
 	return cost;
 }
 
diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp
index 51c56684a91..18412636713 100644
--- a/src/saveload/map_sl.cpp
+++ b/src/saveload/map_sl.cpp
@@ -9,6 +9,7 @@
 
 #include "../stdafx.h"
 #include "../map_func.h"
+#include "../layer_func.h"
 #include "../core/bitmath_func.hpp"
 #include "../fios.h"
 #include <array>
@@ -19,10 +20,12 @@
 
 static uint32 _map_dim_x;
 static uint32 _map_dim_y;
+static uint32 _layer_count;
 
 static const SaveLoadGlobVarList _map_dimensions[] = {
 	SLEG_CONDVAR(_map_dim_x, SLE_UINT32, SLV_6, SL_MAX_VERSION),
 	SLEG_CONDVAR(_map_dim_y, SLE_UINT32, SLV_6, SL_MAX_VERSION),
+	SLEG_CONDVAR(_layer_count, SLE_UINT32, SLV_UNDERGROUND, SL_MAX_VERSION),
 	    SLEG_END()
 };
 
@@ -30,13 +33,16 @@ static void Save_MAPS()
 {
 	_map_dim_x = MapSizeX();
 	_map_dim_y = MapSizeY();
+	_layer_count = LayerCount();
 	SlGlobList(_map_dimensions);
 }
 
 static void Load_MAPS()
 {
 	SlGlobList(_map_dimensions);
-	AllocateMap(_map_dim_x, _map_dim_y);
+	if (IsSavegameVersionBefore(SLV_UNDERGROUND))
+		_layer_count = 1;
+	AllocateMap(_map_dim_x, _map_dim_y/_layer_count, _layer_count);
 }
 
 static void Check_MAPS()
diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h
index abd58ea04e1..2ee369b51fd 100644
--- a/src/saveload/saveload.h
+++ b/src/saveload/saveload.h
@@ -304,6 +304,8 @@ enum SaveLoadVersion : uint16 {
 	SLV_ENDING_YEAR,                        ///< 218  PR#7747 v1.10 Configurable ending year.
 	SLV_REMOVE_TOWN_CARGO_CACHE,            ///< 219  PR#8258 Remove town cargo acceptance and production caches.
 
+	SLV_UNDERGROUND,                        ///< 219  Underground levels.
+
 	SL_MAX_VERSION,                         ///< Highest possible saveload version
 };
 
diff --git a/src/script/api/script_window.hpp.in b/src/script/api/script_window.hpp.in
index a1dbb656705..b0c3656dc6d 100644
--- a/src/script/api/script_window.hpp.in
+++ b/src/script/api/script_window.hpp.in
@@ -65,6 +65,7 @@
 #include "../../widgets/town_widget.h"
 #include "../../widgets/transparency_widget.h"
 #include "../../widgets/tree_widget.h"
+#include "../../widgets/underground_widget.h"
 #include "../../widgets/vehicle_widget.h"
 #include "../../widgets/viewport_widget.h"
 #include "../../widgets/waypoint_widget.h"
diff --git a/src/settings.cpp b/src/settings.cpp
index 505638e94e9..ae0ccb53f6a 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -31,6 +31,7 @@
 #include "command_func.h"
 #include "console_func.h"
 #include "pathfinder/pathfinder_type.h"
+#include "layer_type.h"
 #include "genworld.h"
 #include "train.h"
 #include "news_func.h"
diff --git a/src/settings_type.h b/src/settings_type.h
index fdb2b0f862d..27708eb73b8 100644
--- a/src/settings_type.h
+++ b/src/settings_type.h
@@ -147,6 +147,8 @@ struct GUISettings {
 	byte   starting_colour;                  ///< default color scheme for the company to start a new game with
 	bool   show_newgrf_name;                 ///< Show the name of the NewGRF in the build vehicle window
 
+	uint32 layer_view_type;                   ///< ��������������� (��� �����������)
+
 	uint16 console_backlog_timeout;          ///< the minimum amount of time items should be in the console backlog before they will be removed in ~3 seconds granularity.
 	uint16 console_backlog_length;           ///< the minimum amount of items in the console backlog before items will be removed.
 
@@ -282,6 +284,7 @@ struct GameCreationSettings {
 	Year   ending_year;                      ///< scoring end date
 	uint8  map_x;                            ///< X size of map
 	uint8  map_y;                            ///< Y size of map
+	uint8  layers;                           ///< map layer count
 	byte   land_generator;                   ///< the landscape generator
 	byte   oil_refinery_limit;               ///< distance oil refineries allowed from map edge
 	byte   snow_line_height;                 ///< the configured snow line height
diff --git a/src/station.cpp b/src/station.cpp
index 6f55574acf9..b069ce98659 100644
--- a/src/station.cpp
+++ b/src/station.cpp
@@ -11,6 +11,7 @@
 #include "company_func.h"
 #include "company_base.h"
 #include "roadveh.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "viewport_kdtree.h"
 #include "date_func.h"
@@ -493,7 +494,7 @@ void StationRect::MakeEmpty()
 /**
  * Determines whether a given point (x, y) is within a certain distance of
  * the station rectangle.
- * @note x and y are in Tile coordinates
+ * @note x and y are in Tile coordinates (in top layer)
  * @param x X coordinate
  * @param y Y coordinate
  * @param distance The maximum distance a point may have (L1 norm)
@@ -512,8 +513,10 @@ bool StationRect::IsEmpty() const
 
 CommandCost StationRect::BeforeAddTile(TileIndex tile, StationRectMode mode)
 {
-	int x = TileX(tile);
-	int y = TileY(tile);
+	/*	������� ����� ��������� �� ����� ������.
+	*	�� ���������� ������ �����������		*/
+	int x = LayerX(tile);
+	int y = LayerY(tile);
 	if (this->IsEmpty()) {
 		/* we are adding the first station tile */
 		if (mode != ADD_TEST) {
@@ -566,28 +569,35 @@ CommandCost StationRect::BeforeAddRect(TileIndex tile, int w, int h, StationRect
  */
 /* static */ bool StationRect::ScanForStationTiles(StationID st_id, int left_a, int top_a, int right_a, int bottom_a)
 {
-	TileArea ta(TileXY(left_a, top_a), TileXY(right_a, bottom_a));
-	TILE_AREA_LOOP(tile, ta) {
-		if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == st_id) return true;
+	/*	������� ����� ��������� �� ����� ������.
+	*	������ ���� ������ ��� ����		*/
+	TileArea ta(TopTile(TileXY(left_a, top_a)), TopTile(TileXY(right_a, bottom_a)));
+
+	FOR_ALL_LAYERS(layer) {
+		ta.tile = TopTile(ta.tile) + layer * LayerSize();
+		TILE_AREA_LOOP(tile, ta) {
+			if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == st_id) return true;
+		}
 	}
-
 	return false;
 }
 
 bool StationRect::AfterRemoveTile(BaseStation *st, TileIndex tile)
 {
-	int x = TileX(tile);
-	int y = TileY(tile);
+	/*	������� ����� ��������� �� ����� ������.
+	*	�� ���������� ������ �����������		*/
+	int x = LayerX(tile);
+	int y = LayerY(tile);
 
 	/* look if removed tile was on the bounding rect edge
 	 * and try to reduce the rect by this edge
 	 * do it until we have empty rect or nothing to do */
 	for (;;) {
 		/* check if removed tile is on rect edge */
-		bool left_edge = (x == this->left);
-		bool right_edge = (x == this->right);
-		bool top_edge = (y == this->top);
-		bool bottom_edge = (y == this->bottom);
+		bool left_edge = (x == TopTile(this->left));
+		bool right_edge = (x == TopTile(this->right));
+		bool top_edge = (y == TopTile(this->top));
+		bool bottom_edge = (y == TopTile(this->bottom));
 
 		/* can we reduce the rect in either direction? */
 		bool reduce_x = ((left_edge || right_edge) && !ScanForStationTiles(st->index, x, this->top, x, this->bottom));
@@ -626,8 +636,13 @@ bool StationRect::AfterRemoveTile(BaseStation *st, TileIndex tile)
 
 bool StationRect::AfterRemoveRect(BaseStation *st, TileArea ta)
 {
-	assert(this->PtInExtendedRect(TileX(ta.tile), TileY(ta.tile)));
-	assert(this->PtInExtendedRect(TileX(ta.tile) + ta.w - 1, TileY(ta.tile) + ta.h - 1));
+	/*	������� ����� ��������� �� ����� ������.
+	*	�� ���������� ������ �����������		*/
+	int topx = LayerX(ta.tile);
+	int topy = LayerY(ta.tile);
+
+	assert(this->PtInExtendedRect(topx, topy));
+	assert(this->PtInExtendedRect(topx + ta.w - 1, topy + ta.h - 1));
 
 	bool empty = this->AfterRemoveTile(st, ta.tile);
 	if (ta.w != 1 || ta.h != 1) empty = empty || this->AfterRemoveTile(st, TILE_ADDXY(ta.tile, ta.w - 1, ta.h - 1));
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 7bce21353df..bf1366cb90a 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -11,6 +11,7 @@
 #include "aircraft.h"
 #include "bridge_map.h"
 #include "cmd_helper.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "viewport_kdtree.h"
 #include "command_func.h"
@@ -100,21 +101,24 @@ bool IsHangar(TileIndex t)
  * @return Succeeded command (if zero or one station found) or failed command (for two or more stations found).
  */
 template <class T>
-CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st)
+CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st, bool layers=false)
 {
 	ta.Expand(1);
 
 	/* check around to see if there are any stations there owned by the company */
-	TILE_AREA_LOOP(tile_cur, ta) {
-		if (IsTileType(tile_cur, MP_STATION)) {
-			StationID t = GetStationIndex(tile_cur);
-			if (!T::IsValidID(t) || Station::Get(t)->owner != company) continue;
-			if (closest_station == INVALID_STATION) {
-				closest_station = t;
-			} else if (closest_station != t) {
-				return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
+	FOR_ALL_LAYERS(layer) {
+		TILE_AREA_LOOP(tile_cur, ta) {
+			if (IsTileType(tile_cur, MP_STATION)) {
+				StationID t = GetStationIndex(tile_cur);
+				if (!T::IsValidID(t) || Station::Get(t)->owner != company) continue;
+				if (closest_station == INVALID_STATION) {
+					closest_station = t;
+				} else if (closest_station != t) {
+					return_cmd_error(STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING);
+				}
 			}
 		}
+		if (!layers) break;
 	}
 	*st = (closest_station == INVALID_STATION) ? nullptr : T::Get(closest_station);
 	return CommandCost();
@@ -811,7 +815,7 @@ CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z
 				return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
 			}
 		}
-		cost.AddCost(_price[PR_BUILD_FOUNDATION]);
+		cost.AddCost(_price[PR_BUILD_FOUNDATION] * UNDERGROUND_COST_MULTIPLIER(tile));
 	}
 
 	/* The level of this tile must be equal to allowed_z. */
@@ -1049,7 +1053,7 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags
 				ret = DoCommand(cur_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 				if (ret.Failed()) return ret;
 				cost.AddCost(ret);
-				cost.AddCost(RoadBuildCost(rt) * 2);
+				cost.AddCost(RoadBuildCost(rt) * 2 * UNDERGROUND_COST_MULTIPLIER(cur_tile));
 			}
 		}
 	}
@@ -1069,11 +1073,13 @@ CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta, Axis a
 	TileArea cur_ta = st->train_station;
 
 	/* determine new size of train station region.. */
-	int x = min(TileX(cur_ta.tile), TileX(new_ta.tile));
-	int y = min(TileY(cur_ta.tile), TileY(new_ta.tile));
-	new_ta.w = max(TileX(cur_ta.tile) + cur_ta.w, TileX(new_ta.tile) + new_ta.w) - x;
-	new_ta.h = max(TileY(cur_ta.tile) + cur_ta.h, TileY(new_ta.tile) + new_ta.h) - y;
-	new_ta.tile = TileXY(x, y);
+	/*	����������, ��������� ������� ("���������") ������ ������ �����.
+	*	������� �������� ������ � �������� ������ ����	 	*/
+	int topx = min(LayerX(cur_ta.tile), LayerX(new_ta.tile));
+	int topy = min(LayerY(cur_ta.tile), LayerY(new_ta.tile));
+	new_ta.w = max(LayerX(cur_ta.tile) + cur_ta.w, LayerX(new_ta.tile) + new_ta.w) - topx;
+	new_ta.h = max(LayerY(cur_ta.tile) + cur_ta.h, LayerY(new_ta.tile) + new_ta.h) - topy;
+	new_ta.tile = TileXY(topx, topy);
 
 	/* make sure the final size is not too big. */
 	if (new_ta.w > _settings_game.station.station_spread || new_ta.h > _settings_game.station.station_spread) {
@@ -1145,7 +1151,7 @@ void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSp
  * @return command cost with the error or 'okay'
  */
 template <class T, StringID error_message>
-CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st)
+CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st, bool layers=false)
 {
 	assert(*st == nullptr);
 	bool check_surrounding = true;
@@ -1171,7 +1177,7 @@ CommandCost FindJoiningBaseStation(StationID existing_station, StationID station
 
 	if (check_surrounding) {
 		/* Make sure there is no more than one other station around us that is owned by us. */
-		CommandCost ret = GetStationAround(ta, existing_station, _current_company, st);
+		CommandCost ret = GetStationAround(ta, existing_station, _current_company, st, layers);
 		if (ret.Failed()) return ret;
 	}
 
@@ -1190,9 +1196,9 @@ CommandCost FindJoiningBaseStation(StationID existing_station, StationID station
  * @param st 'return' pointer for the found station
  * @return command cost with the error or 'okay'
  */
-static CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
+static CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st, bool layers=false)
 {
-	return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_RAILWAY_STATION_FIRST>(existing_station, station_to_join, adjacent, ta, st);
+	return FindJoiningBaseStation<Station, STR_ERROR_MUST_REMOVE_RAILWAY_STATION_FIRST>(existing_station, station_to_join, adjacent, ta, st, layers);
 }
 
 /**
@@ -1301,8 +1307,8 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
 	CommandCost cost = CheckFlatLandRailStation(new_location, flags, axis, &est, rt, affected_vehicles, spec_class, spec_index, plat_len, numtracks);
 	if (cost.Failed()) return cost;
 	/* Add construction expenses. */
-	cost.AddCost((numtracks * _price[PR_BUILD_STATION_RAIL] + _price[PR_BUILD_STATION_RAIL_LENGTH]) * plat_len);
-	cost.AddCost(numtracks * plat_len * RailBuildCost(rt));
+	cost.AddCost((numtracks * _price[PR_BUILD_STATION_RAIL] + _price[PR_BUILD_STATION_RAIL_LENGTH]) * plat_len * UNDERGROUND_COST_MULTIPLIER(tile_org));
+	cost.AddCost(numtracks * plat_len * RailBuildCost(rt) * UNDERGROUND_COST_MULTIPLIER(tile_org));
 
 	Station *st = nullptr;
 	ret = FindJoiningStation(est, station_to_join, adjacent, new_location, &st);
@@ -1342,8 +1348,10 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
 		byte numtracks_orig;
 		Track track;
 
+		TileIndex top_tile = TopTile(new_location.tile);
 		st->train_station = new_location;
-		st->AddFacility(FACIL_TRAIN, new_location.tile);
+		st->train_station.tile = top_tile;
+		st->AddFacility(FACIL_TRAIN, tile_org);
 
 		st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TRY);
 
@@ -1583,7 +1591,7 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector<T *> &affected_st
 		}
 
 		/* If we reached here, the tile is valid so increase the quantity of tiles we will remove */
-		quantity++;
+		quantity += UNDERGROUND_COST_MULTIPLIER(tile);
 
 		if (keep_rail || IsStationTileBlocked(tile)) {
 			/* Don't refund the 'steel' of the track when we keep the
@@ -1662,7 +1670,7 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector<T *> &affected_st
 CommandCost CmdRemoveFromRailStation(TileIndex start, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
 	TileIndex end = p1 == 0 ? start : p1;
-	if (start >= MapSize() || end >= MapSize()) return CMD_ERROR;
+	if (start >= MapSize() || end >= MapSize() || (LayerIndex(start) != LayerIndex(end))) return CMD_ERROR;
 
 	TileArea ta(start, end);
 	std::vector<Station *> affected_stations;
@@ -1725,11 +1733,16 @@ CommandCost RemoveRailStation(T *st, DoCommandFlag flags, Money removal_cost)
 	/* determine width and height of platforms */
 	TileArea ta = st->train_station;
 
-	assert(ta.w != 0 && ta.h != 0);
+	/*	TileArea is top finite area	*/
+	assert(IsTopTile(ta.tile));
+	assert(ta.IsFinite());
 
 	CommandCost cost(EXPENSES_CONSTRUCTION);
+	/* Check all layers */
+	FOR_ALL_LAYERS(layer)
 	/* clear all areas of the station */
-	TILE_AREA_LOOP(tile, ta) {
+	TILE_AREA_LOOP(top_tile, ta) {
+		TileIndex tile = top_tile + layer * LayerSize();
 		/* only remove tiles that are actually train station tiles */
 		if (st->TileBelongsToRailStation(tile)) {
 			std::vector<T*> affected_stations; // dummy
@@ -2095,13 +2108,21 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
 	/* Bankrupting company is not supposed to remove roads, there may be road vehicles. */
 	if (!keep_drive_through_roads && (flags & DC_BANKRUPT)) return CMD_ERROR;
 
-	TileArea roadstop_area(tile, width, height);
+	/*	��� ���������� �������� ��������� (�� ����� ���������)	*/
+	TileArea roadstop_area(TopTile(tile), width, height);
+
+	/*	TileArea is top finite area	*/
+	assert(IsTopTile(roadstop_area.tile));
+	assert(roadstop_area.IsFinite());
 
 	CommandCost cost(EXPENSES_CONSTRUCTION);
 	CommandCost last_error(STR_ERROR_THERE_IS_NO_STATION);
 	bool had_success = false;
 
-	TILE_AREA_LOOP(cur_tile, roadstop_area) {
+	/* Check all layers */
+	FOR_ALL_LAYERS(layer)
+	TILE_AREA_LOOP(top_tile, roadstop_area) {
+		TileIndex cur_tile = top_tile + layer * LayerSize();
 		/* Make sure the specified tile is a road stop of the correct type */
 		if (!IsTileType(cur_tile, MP_STATION) || !IsRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue;
 
@@ -2271,6 +2292,10 @@ CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
 	if (w > _settings_game.station.station_spread || h > _settings_game.station.station_spread) {
 		return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
 	}
+       /* can't make underground airport  */
+       if (IsUnderground(tile)) {
+               return_cmd_error(STR_ERROR_UNDERGROUND_CAN_T_BUILD_UNDER_GROUND);
+       }
 
 	AirportTileTableIterator iter(as->table[layout], tile);
 	CommandCost cost = CheckFlatLandAirport(iter, flags);
diff --git a/src/station_gui.cpp b/src/station_gui.cpp
index 66a4605ea84..ee6d8df5305 100644
--- a/src/station_gui.cpp
+++ b/src/station_gui.cpp
@@ -19,6 +19,7 @@
 #include "strings_func.h"
 #include "string_func.h"
 #include "window_func.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "widgets/dropdown_func.h"
 #include "station_base.h"
@@ -2211,20 +2212,27 @@ static const T *FindStationsNearby(TileArea ta, bool distant_join)
 	_deleted_stations_nearby.clear();
 
 	/* Check the inside, to return, if we sit on another station */
-	TILE_AREA_LOOP(t, ta) {
-		if (t < MapSize() && IsTileType(t, MP_STATION) && T::IsValidID(GetStationIndex(t))) return T::GetByTile(t);
+	FOR_ALL_LAYERS(layer) {
+		TILE_AREA_LOOP(tile, ta) {
+			TileIndex t = TopTile(tile) + layer * LayerSize();
+			if (t < MapSize() && IsTileType(t, MP_STATION) && T::IsValidID(GetStationIndex(t)))
+			{
+				if (t == tile) return T::GetByTile(t);
+				AddNearbyStation<T>(t, &ctx);
+			}
+		}
 	}
 
 	/* Look for deleted stations */
 	for (const BaseStation *st : BaseStation::Iterate()) {
 		if (T::IsExpected(st) && !st->IsInUse() && st->owner == _local_company) {
 			/* Include only within station spread (yes, it is strictly less than) */
-			if (max(DistanceMax(ta.tile, st->xy), DistanceMax(TILE_ADDXY(ta.tile, ta.w - 1, ta.h - 1), st->xy)) < _settings_game.station.station_spread) {
+			if (max(DistanceMax(TopTile(ta.tile), TopTile(st->xy)), DistanceMax(TILE_ADDXY(TopTile(ta.tile), ta.w - 1, ta.h - 1), TopTile(st->xy))) < _settings_game.station.station_spread) {
 				_deleted_stations_nearby.push_back({st->xy, st->index});
 
 				/* Add the station when it's within where we're going to build */
-				if (IsInsideBS(TileX(st->xy), TileX(ctx.tile), ctx.w) &&
-						IsInsideBS(TileY(st->xy), TileY(ctx.tile), ctx.h)) {
+				if (IsInsideBS(LayerX(st->xy), LayerX(ctx.tile), ctx.w) &&
+						IsInsideBS(LayerY(st->xy), LayerY(ctx.tile), ctx.h)) {
 					AddNearbyStation<T>(st->xy, &ctx);
 				}
 			}
@@ -2237,8 +2245,11 @@ static const T *FindStationsNearby(TileArea ta, bool distant_join)
 	if (distant_join && min(ta.w, ta.h) >= _settings_game.station.station_spread) return nullptr;
 	uint max_dist = distant_join ? _settings_game.station.station_spread - min(ta.w, ta.h) : 1;
 
-	TileIndex tile = TileAddByDir(ctx.tile, DIR_N);
-	CircularTileSearch(&tile, max_dist, ta.w, ta.h, AddNearbyStation<T>, &ctx);
+	FOR_ALL_LAYERS(layer) {
+		ctx.tile = TopTile(ctx.tile) + layer * LayerSize();
+		TileIndex tile = TileAddByDir(ctx.tile, DIR_N);
+		CircularTileSearch(&tile, max_dist, ta.w, ta.h, AddNearbyStation<T>, &ctx);
+	}
 
 	return nullptr;
 }
diff --git a/src/table/settings.ini b/src/table/settings.ini
index c7dbd2128bc..50f18c98061 100644
--- a/src/table/settings.ini
+++ b/src/table/settings.ini
@@ -1912,6 +1912,15 @@ min      = 500
 max      = 1000000
 cat      = SC_EXPERT
 
+[SDT_VAR]
+base     = GameSettings
+var      = game_creation.layers
+type     = SLE_UINT8
+flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
+def      = 1
+min      = MIN_LAYER_COUNT_BITS
+max      = MAX_LAYER_COUNT_BITS
+
 [SDT_BOOL]
 base     = GameSettings
 var      = pf.yapf.rail_firstred_twoway_eol
@@ -3240,6 +3249,15 @@ strhelp  = STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT
 strval   = STR_JUST_COMMA
 proc     = RedrawScreen
 
+[SDTC_VAR]
+var      = gui.layer_view_type
+type     = SLE_UINT32
+flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
+def      = 0
+min      = 0
+max      = UINT32_MAX
+proc     = RedrawScreen
+
 [SDTC_BOOL]
 var      = gui.show_newgrf_name
 flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp
index 85edb731289..5b12689403a 100644
--- a/src/terraform_cmd.cpp
+++ b/src/terraform_cmd.cpp
@@ -8,6 +8,7 @@
 /** @file terraform_cmd.cpp Commands related to terraforming. */
 
 #include "stdafx.h"
+#include "layer_func.h"
 #include "command_func.h"
 #include "tunnel_map.h"
 #include "bridge_map.h"
@@ -251,6 +252,10 @@ CommandCost CmdTerraformLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
 			if (z_N > z_min) tileh |= SLOPE_N;
 
 			if (pass == 0) {
+				/*	Terrafrom enable only top layer	*/
+				if (IsUnderground(tile)) {
+					return_cmd_error(STR_ERROR_UNDERGROUND_CAN_T_TERRAFORM);
+				}
 				/* Check if bridge would take damage */
 				if (IsBridgeAbove(tile)) {
 					int bridge_height = GetBridgeHeight(GetSouthernBridgeEnd(tile));
diff --git a/src/tgp.cpp b/src/tgp.cpp
index fb5c69cf758..feeab2525b0 100644
--- a/src/tgp.cpp
+++ b/src/tgp.cpp
@@ -12,6 +12,7 @@
 #include "clear_map.h"
 #include "void_map.h"
 #include "genworld.h"
+#include "layer_func.h"
 #include "core/random_func.hpp"
 #include "landscape_type.h"
 
@@ -168,6 +169,8 @@ struct HeightMap
 	int      total_size; //< height map total size
 	int      size_x;     //< MapSizeX()
 	int      size_y;     //< MapSizeY()
+	int      map_x;	     //< MapSizeX()
+	int      map_y;      //< MapSizeY()
 
 	/**
 	 * Height map accessor
@@ -305,8 +308,11 @@ static inline bool AllocHeightMap()
 {
 	height_t *h;
 
-	_height_map.size_x = MapSizeX();
-	_height_map.size_y = MapSizeY();
+	_height_map.map_x = MapSizeX();
+	_height_map.map_y = MapSizeY();
+
+	_height_map.size_x = LayerSizeX();
+	_height_map.size_y = LayerSizeY();
 
 	/* Allocate memory block for height map row pointers */
 	_height_map.total_size = (_height_map.size_x + 1) * (_height_map.size_y + 1);
@@ -993,8 +999,8 @@ void GenerateTerrainPerlin()
 
 	/* First make sure the tiles at the north border are void tiles if needed. */
 	if (_settings_game.construction.freeform_edges) {
-		for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0));
-		for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y));
+		for (uint x = 0; x < _height_map.map_x;     x++) MakeVoid(x);
+		for (uint y = 0; y < _height_map.map_y - 1; y++) MakeVoid(_height_map.size_x * y);
 	}
 
 	int max_height = H2I(TGPGetMaxHeight());
diff --git a/src/tile_map.h b/src/tile_map.h
index b6c715e8a8b..c191ab90423 100644
--- a/src/tile_map.h
+++ b/src/tile_map.h
@@ -14,6 +14,7 @@
 #include "map_func.h"
 #include "core/bitmath_func.hpp"
 #include "settings_type.h"
+#include "layer_func.h"
 
 /**
  * Returns the height of a tile
@@ -110,10 +111,10 @@ static inline bool IsInnerTile(TileIndex tile)
 {
 	assert(tile < MapSize());
 
-	uint x = TileX(tile);
-	uint y = TileY(tile);
+	uint x = LayerX(tile);
+	uint y = LayerY(tile);
 
-	return x < MapMaxX() && y < MapMaxY() && ((x > 0 && y > 0) || !_settings_game.construction.freeform_edges);
+	return x < LayerMaxX() && y < LayerMaxY() && ((x > 0 && y > 0) || !_settings_game.construction.freeform_edges);
 }
 
 /**
@@ -134,7 +135,7 @@ static inline void SetTileType(TileIndex tile, TileType type)
 	/* VOID tiles (and no others) are exactly allowed at the lower left and right
 	 * edges of the map. If _settings_game.construction.freeform_edges is true,
 	 * the upper edges of the map are also VOID tiles. */
-	assert(IsInnerTile(tile) == (type != MP_VOID));
+	assert(IsInnerTile(tile) == (type != MP_VOID)); // was commented in <underground>
 	SB(_m[tile].type, 4, 4, type);
 }
 
diff --git a/src/tilearea_type.h b/src/tilearea_type.h
index 26482198537..76971ae48ae 100644
--- a/src/tilearea_type.h
+++ b/src/tilearea_type.h
@@ -42,6 +42,16 @@ struct OrthogonalTileArea {
 		this->h    = 0;
 	}
 
+	inline bool IsEmpty() const
+	{
+		return (w==0 && h==0);
+	}
+
+	inline bool IsFinite() const
+	{
+		return (w!=0 && h!=0);
+	}
+
 	bool Intersects(const OrthogonalTileArea &ta) const;
 
 	bool Contains(TileIndex tile) const;
diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp
index 632025ddb4c..3be7b0c1418 100644
--- a/src/toolbar_gui.cpp
+++ b/src/toolbar_gui.cpp
@@ -11,7 +11,10 @@
 #include "gui.h"
 #include "window_gui.h"
 #include "window_func.h"
+#include "layer_gui.h"
+#include "layer_func.h"
 #include "viewport_func.h"
+#include "landscape.h"
 #include "command_func.h"
 #include "vehicle_gui.h"
 #include "rail_gui.h"
@@ -21,6 +24,7 @@
 #include "vehicle_func.h"
 #include "sound_func.h"
 #include "terraform_gui.h"
+#include "underground_gui.h"
 #include "strings_func.h"
 #include "company_func.h"
 #include "company_gui.h"
@@ -1006,6 +1010,39 @@ static CallBackFunction MenuClickForest(int index)
 	return CBF_NONE;
 }
 
+/* --- Underground button menu --- */
+
+/**
+ * Handle click on the entry in the underground menu.
+ *
+ * @param index Menu entry clicked.
+ * @return #CBF_NONE
+ */
+static CallBackFunction MenuClickUnderground(int index)
+{
+	if (index==0) {
+		ShowUndergroundToolbar();
+		return CBF_NONE;
+	}
+	index -= 1;
+	if ((index<0) || (uint(index) >= LayerCount()))
+		return CBF_NONE;
+	Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
+	int delta_layer = calculateLayer(w->viewport) - index;
+	Point pt = RemapCoords(0, -delta_layer * LayerSizeY() * TILE_SIZE, 0);
+	w->viewport->dest_scrollpos_x += pt.x;
+	w->viewport->dest_scrollpos_y += pt.y;
+	w->InvalidateData();
+	return CBF_NONE;
+}
+
+static CallBackFunction ToolbarUndergroundClick(Window *w)
+{
+	PopupMainToolbMenu(w, WID_TN_UNDERGROUND, STR_LANDSCAPING_MENU_UNDERGROUND, 1+LayerCount());
+	if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
+	return CBF_NONE;
+}
+
 /* --- Music button menu --- */
 
 static CallBackFunction ToolbarMusicClick(Window *w)
@@ -1316,9 +1353,10 @@ static MenuClickedProc * const _menu_clicked_procs[] = {
 	MenuClickBuildWater,  // 24
 	MenuClickBuildAir,    // 25
 	MenuClickForest,      // 26
-	MenuClickMusicWindow, // 27
-	MenuClickNewspaper,   // 28
-	MenuClickHelp,        // 29
+	MenuClickUnderground, // 27
+	MenuClickMusicWindow, // 28
+	MenuClickNewspaper,   // 29
+	MenuClickHelp,        // 30
 };
 
 /** Full blown container to make it behave exactly as we want :) */
@@ -1483,7 +1521,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
 	const byte *GetButtonArrangement(uint &width, uint &arrangable_count, uint &button_count, uint &spacer_count) const override
 	{
 		static const uint SMALLEST_ARRANGEMENT = 14;
-		static const uint BIGGEST_ARRANGEMENT  = 20;
+		static const uint BIGGEST_ARRANGEMENT  = 21;
 
 		/* The number of buttons of each row of the toolbar should match the number of items which we want to be visible.
 		 * The total number of buttons should be equal to arrangable_count * 2.
@@ -1750,6 +1788,67 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
 			WID_TN_ZOOM_OUT,
 			WID_TN_SWITCH_BAR,
 		};
+		static const byte arrange21[] = {
+			WID_TN_PAUSE,
+			WID_TN_FAST_FORWARD,
+			WID_TN_SETTINGS,
+			WID_TN_SMALL_MAP,
+			WID_TN_TOWNS,
+			WID_TN_SUBSIDIES,
+			WID_TN_STATIONS,
+			WID_TN_FINANCES,
+			WID_TN_COMPANIES,
+			WID_TN_STORY,
+			WID_TN_GOAL,
+			WID_TN_GRAPHS,
+			WID_TN_LEAGUE,
+			WID_TN_INDUSTRIES,
+			WID_TN_TRAINS,
+			WID_TN_ROADVEHS,
+			WID_TN_SHIPS,
+			WID_TN_AIRCRAFT,
+			WID_TN_ZOOM_IN,
+			WID_TN_ZOOM_OUT,
+			WID_TN_RAILS,
+			WID_TN_ROADS,
+			WID_TN_WATER,
+			WID_TN_AIR,
+			WID_TN_LANDSCAPE,
+			WID_TN_UNDERGROUND,
+			WID_TN_MUSIC_SOUND,
+			WID_TN_MESSAGES,
+			WID_TN_HELP,
+			// lower toolbar
+			WID_TN_PAUSE,
+			WID_TN_FAST_FORWARD,
+			WID_TN_SAVE,
+			WID_TN_SMALL_MAP,
+			WID_TN_TOWNS,
+			WID_TN_SUBSIDIES,
+			WID_TN_STATIONS,
+			WID_TN_FINANCES,
+			WID_TN_COMPANIES,
+			WID_TN_STORY,
+			WID_TN_GOAL,
+			WID_TN_GRAPHS,
+			WID_TN_LEAGUE,
+			WID_TN_INDUSTRIES,
+			WID_TN_TRAINS,
+			WID_TN_ROADVEHS,
+			WID_TN_SHIPS,
+			WID_TN_AIRCRAFT,
+			WID_TN_ZOOM_IN,
+			WID_TN_ZOOM_OUT,
+			WID_TN_RAILS,
+			WID_TN_ROADS,
+			WID_TN_WATER,
+			WID_TN_AIR,
+			WID_TN_LANDSCAPE,
+			WID_TN_UNDERGROUND,
+			WID_TN_MUSIC_SOUND,
+			WID_TN_MESSAGES,
+			WID_TN_HELP,
+		};
 		static const byte arrange_all[] = {
 			WID_TN_PAUSE,
 			WID_TN_FAST_FORWARD,
@@ -1778,6 +1877,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
 			WID_TN_WATER,
 			WID_TN_AIR,
 			WID_TN_LANDSCAPE,
+			WID_TN_UNDERGROUND,
 			WID_TN_MUSIC_SOUND,
 			WID_TN_MESSAGES,
 			WID_TN_HELP
@@ -1792,7 +1892,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
 		}
 
 		/* Introduce the split toolbar */
-		static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20 };
+		static const byte * const arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19, arrange20, arrange21 };
 
 		button_count = arrangable_count = full_buttons;
 		spacer_count = this->spacers;
@@ -1949,6 +2049,7 @@ static ToolbarButtonProc * const _toolbar_button_procs[] = {
 	ToolbarBuildWaterClick,
 	ToolbarBuildAirClick,
 	ToolbarForestClick,
+	ToolbarUndergroundClick,
 	ToolbarMusicClick,
 	ToolbarNewspaperClick,
 	ToolbarHelpClick,
@@ -2245,6 +2346,7 @@ static NWidgetBase *MakeMainToolbar(int *biggest_index)
 		SPR_IMG_BUILDWATER,      // WID_TN_WATER
 		SPR_IMG_BUILDAIR,        // WID_TN_AIR
 		SPR_IMG_LANDSCAPING,     // WID_TN_LANDSCAPE
+		SPR_IMG_LANDSCAPING,     // WID_TN_UNDERGROUND
 		SPR_IMG_MUSIC,           // WID_TN_MUSIC_SOUND
 		SPR_IMG_MESSAGES,        // WID_TN_MESSAGES
 		SPR_IMG_QUERY,           // WID_TN_HELP
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index 374601cad23..41e5f487af8 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -12,6 +12,7 @@
 #include "road_internal.h" /* Cleaning up road bits */
 #include "road_cmd.h"
 #include "landscape.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "viewport_kdtree.h"
 #include "cmd_helper.h"
@@ -2016,7 +2017,7 @@ static Town *CreateRandomTown(uint attempts, uint32 townnameparts, TownSize size
 
 	do {
 		/* Generate a tile index not too close from the edge */
-		TileIndex tile = AlignTileToGrid(RandomTile(), layout);
+		TileIndex tile = AlignTileToGrid(TopTile(RandomTile()), layout);
 
 		/* if we tried to place the town on water, slide it over onto
 		 * the nearest likely-looking spot */
@@ -2192,6 +2193,9 @@ static inline bool CanBuildHouseHere(TileIndex tile, bool noslope)
 	Slope slope = GetTileSlope(tile);
 	if ((noslope && slope != SLOPE_FLAT) || IsSteepSlope(slope)) return false;
 
+	/*	����������� ������������� ������� ��� ������	*/
+	if (IsUnderground(tile)) return false;
+
 	/* at least one RoadTypes allow building the house here? */
 	if (!RoadTypesAllowHouseHere(tile)) return false;
 
@@ -2627,6 +2631,8 @@ CommandCost CmdRenameTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
 		InvalidateWindowData(WC_TOWN_DIRECTORY, 0, TDIWD_FORCE_RESORT);
 		ClearAllStationCachedNames();
 		ClearAllIndustryCachedNames();
+		InvalidateWindowClassesData(WC_TOWN_VIEW);
+		InvalidateWindowClassesData(WC_INDUSTRY_VIEW);
 		UpdateAllStationVirtCoords();
 	}
 	return CommandCost();
diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp
index cdc98692075..2e95b25a295 100644
--- a/src/tree_cmd.cpp
+++ b/src/tree_cmd.cpp
@@ -11,6 +11,7 @@
 #include "clear_map.h"
 #include "landscape.h"
 #include "tree_map.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "command_func.h"
 #include "town.h"
@@ -70,7 +71,8 @@ static bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert)
 
 		case MP_CLEAR:
 			return !IsBridgeAbove(tile) && !IsClearGround(tile, CLEAR_FIELDS) && GetRawClearGround(tile) != CLEAR_ROCKS &&
-			       (allow_desert || !IsClearGround(tile, CLEAR_DESERT));
+			       (allow_desert || !IsClearGround(tile, CLEAR_DESERT))
+				   && !IsUnderground(tile);
 
 		default: return false;
 	}
@@ -184,7 +186,7 @@ static void PlaceTree(TileIndex tile, uint32 r)
 static void PlaceTreeGroups(uint num_groups)
 {
 	do {
-		TileIndex center_tile = RandomTile();
+		TileIndex center_tile = TopTile(RandomTile());
 
 		for (uint i = 0; i < DEFAULT_TREE_STEPS; i++) {
 			uint32 r = Random();
@@ -249,7 +251,7 @@ void PlaceTreesRandomly()
 	if (_game_mode == GM_EDITOR) i /= EDITOR_TREE_DIV;
 	do {
 		uint32 r = Random();
-		TileIndex tile = RandomTileSeed(r);
+		TileIndex tile = TopTile(RandomTileSeed(r));
 
 		IncreaseGeneratingWorldProgress(GWP_TREE);
 
@@ -278,7 +280,7 @@ void PlaceTreesRandomly()
 
 		do {
 			uint32 r = Random();
-			TileIndex tile = RandomTileSeed(r);
+			TileIndex tile = TopTile(RandomTileSeed(r));
 
 			IncreaseGeneratingWorldProgress(GWP_TREE);
 
@@ -337,6 +339,10 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
 	const byte tree_to_plant = GB(p1, 0, 8); // We cannot use Extract as min and max are climate specific.
 
 	if (p2 >= MapSize()) return CMD_ERROR;
+
+	/*	tree only top layer	*/
+	if (IsUnderground(p2)) return CMD_ERROR;
+
 	/* Check the tree type within the current climate */
 	if (tree_to_plant != TREE_INVALID && !IsInsideBS(tree_to_plant, _tree_base_by_landscape[_settings_game.game_creation.landscape], _tree_count_by_landscape[_settings_game.game_creation.landscape])) return CMD_ERROR;
 
@@ -764,7 +770,7 @@ void OnTick_Trees()
 
 	/* place a tree at a random rainforest spot */
 	if (_settings_game.game_creation.landscape == LT_TROPIC &&
-			(r = Random(), tile = RandomTileSeed(r), GetTropicZone(tile) == TROPICZONE_RAINFOREST) &&
+			(r = Random(), tile = TopTile(RandomTileSeed(r)), GetTropicZone(tile) == TROPICZONE_RAINFOREST) &&
 			CanPlantTreesOnTile(tile, false) &&
 			(tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) {
 		PlantTreesOnTile(tile, tree, 0, 0);
@@ -775,7 +781,7 @@ void OnTick_Trees()
 
 	/* place a tree at a random spot */
 	r = Random();
-	tile = RandomTileSeed(r);
+	tile = TopTile(RandomTileSeed(r));
 	if (CanPlantTreesOnTile(tile, false) && (tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TREE_INVALID) {
 		PlantTreesOnTile(tile, tree, 0, 0);
 	}
diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp
index 1a66d530f06..5b12e7c204d 100644
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -13,6 +13,7 @@
 
 #include "stdafx.h"
 #include "newgrf_object.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "cmd_helper.h"
 #include "command_func.h"
@@ -277,6 +278,10 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
 		return_cmd_error(STR_ERROR_CAN_T_START_AND_END_ON);
 	}
 
+	if (IsUnderground(tile_start) || IsUnderground(tile_end)) {
+		return_cmd_error(STR_ERROR_UNDERGROUND_CAN_T_BUILD_UNDER_GROUND);
+	}
+
 	Axis direction;
 	if (TileX(tile_start) == TileX(tile_end)) {
 		direction = AXIS_Y;
@@ -670,6 +675,12 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
 	for (;;) {
 		end_tile += delta;
 		if (!IsValidTile(end_tile)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER);
+
+
+		if (IsUnderground(start_tile) || IsUnderground(end_tile)) {
+			return_cmd_error(STR_ERROR_UNDERGROUND_CAN_T_BUILD_UNDER_GROUND);
+		}
+
 		end_tileh = GetTileSlope(end_tile, &end_z);
 
 		if (start_z == end_z) break;
diff --git a/src/underground_gui.cpp b/src/underground_gui.cpp
new file mode 100644
index 00000000000..406bd8cb7d1
--- /dev/null
+++ b/src/underground_gui.cpp
@@ -0,0 +1,321 @@
+/* $Id: terraform_gui.cpp 23547 2011-12-16 18:21:13Z truebrain $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file terraform_gui.cpp GUI related to terraforming the map. */
+
+#include "stdafx.h"
+#include "clear_map.h"
+#include "company_func.h"
+#include "company_base.h"
+#include "gui.h"
+#include "window_gui.h"
+#include "window_func.h"
+#include "layer_func.h"
+#include "viewport_func.h"
+#include "command_func.h"
+#include "signs_func.h"
+#include "sound_func.h"
+#include "base_station_base.h"
+#include "textbuf_gui.h"
+#include "genworld.h"
+#include "tree_map.h"
+#include "landscape_type.h"
+#include "tilehighlight_func.h"
+#include "strings_func.h"
+#include "newgrf_object.h"
+#include "newgrf_station.h"
+#include "object.h"
+#include "hotkeys.h"
+#include "engine_base.h"
+
+#include "widgets/underground_widget.h"
+
+#include "table/strings.h"
+#include "error.h"
+
+void ShowError(TileIndex tile, CommandCost res, uint32 cmd)
+{
+	int x = TileX(tile) * TILE_SIZE;
+	int y = TileY(tile) * TILE_SIZE;
+	StringID error_part1 = GB(cmd, 16, 16);
+
+	if (IsLocalCompany() && error_part1 != 0) {
+		ShowErrorMessage(error_part1, res.GetErrorMessage(), WL_INFO, x, y, res.GetTextRefStackGRF(), res.GetTextRefStackSize(), res.GetTextRefStack());
+	}
+}
+
+
+/**
+ * Place a escalator.
+ * @param tile Position to place or start dragging a station.
+ */
+static void PlaceUnderground_Escalator(TileIndex tile)
+{
+	RailType railtype = RAILTYPE_RAIL;
+	Axis orientation = AXIS_X;
+	StationClassID station_class = STAT_CLASS_DFLT;
+	byte station_type = 0;
+
+	uint32 p1 = railtype | orientation << 4 | 1 << 8 | 1 << 16 | _ctrl_pressed << 24;
+	uint32 p2 = station_class | station_type << 8 | INVALID_STATION << 16;
+
+	int w = 1;
+	int h = 1;
+
+	uint top_tile = TopTile(tile);
+	uint base_tile = tile;
+	bool from_top = false;	//	������ �� �������� ����
+
+	if (top_tile == base_tile)
+	{
+		from_top = true;
+		base_tile += LayerSize();
+	};
+
+	uint32 cmdS = CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_UNDERGROUND_CAN_T_BUILD_PART);
+	uint32 cmdT = CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_UNDERGROUND_CAN_T_BUILD_TOP_PART);
+	uint32 cmdB = CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_UNDERGROUND_CAN_T_BUILD_BOTTOM_PART);
+	CommandContainer cmdTop = { top_tile, p1, p2, cmdT, CcStation, "" };
+	CommandContainer cmdBase = { base_tile, p1, p2, cmdB, CcStation, "" };
+
+	DoCommandFlag flags = DC_AUTO | DC_NO_WATER;
+	CommandCost resTop;
+	CommandCost res;
+
+	//	��������� ����������� ��������� ����� � ����:
+	resTop=DoCommand(&cmdTop, flags | DC_QUERY_COST);
+	if (resTop.Failed())
+	{
+		ShowError(tile, resTop, cmdT);
+		return;
+	}
+
+	res=DoCommand(&cmdBase, flags | DC_QUERY_COST);
+	if (res.Failed())
+	{
+		ShowError(tile, res, cmdB);
+		return;
+	}
+
+	res.AddCost(resTop.GetCost());
+	if (_shift_pressed || !CheckCompanyHasMoney(res))
+	{
+		if (res.Failed()) ShowError(tile, res, cmdS);
+		else ShowEstimatedCostOrIncome(res.GetCost(), TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE);
+		return;
+	}
+
+	//	������� ����� ���� ������ � �����.
+	//	����� �� ���� ���������, ����� ������� �� ��������� ����
+	CommandContainer *cmd1 = from_top ? &cmdTop : &cmdBase;
+	CommandContainer *cmd2 = from_top ? &cmdBase : &cmdTop;
+
+	//	������ ������� (� �������� ����)
+	res=DoCommand(cmd1, flags | DC_EXEC);
+	assert(!res.Failed());
+
+	//	�������� ���������
+	StationID station = GetStationIndex(cmd1->tile);
+	cmd2->p2 = station_class | station_type << 8 | station << 16;
+
+	//	������ ������� (� ������ ����)
+	res=DoCommand(cmd2, flags | DC_EXEC);
+	assert(!res.Failed());
+}
+
+/** Underground toolbar managing class. */
+struct UndergroundToolbarWindow : Window {
+	int last_user_action; ///< Last started user action.
+
+	UndergroundToolbarWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
+	{
+		/* This is needed as we like to have the tree available on OnInit. */
+		this->CreateNestedTree(desc);
+		this->FinishInitNested(window_number);
+		this->last_user_action = WIDGET_LIST_END;
+	}
+
+	~UndergroundToolbarWindow()
+	{
+	}
+
+	virtual void OnInit()
+	{
+	}
+
+	virtual void OnClick(Point pt, int widget, int click_count)
+	{
+		switch (widget) {
+			case WID_UT_BUILD_ESCALATOR: // WID_TT_BUILD_ESCALATOR
+				HandlePlacePushButton(this, WID_UT_BUILD_ESCALATOR, SPR_CURSOR_RAIL_STATION, HT_RECT);
+				this->last_user_action = widget;
+				break;
+
+			case WID_UT_DEMOLISH: // Demolish aka dynamite button
+				HandlePlacePushButton(this, WID_UT_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT | HT_DIAGONAL);
+				this->last_user_action = widget;
+				break;
+
+			default: NOT_REACHED();
+		}
+	}
+
+	virtual void OnTimeout()
+	{
+	}
+
+	virtual void OnPlaceObject(Point pt, TileIndex tile)
+	{
+		switch (this->last_user_action) {
+			case WID_UT_BUILD_ESCALATOR:
+				PlaceUnderground_Escalator(tile);
+				break;
+
+			case WID_UT_DEMOLISH: // Demolish aka dynamite button
+				PlaceProc_DemolishArea(tile);
+				break;
+
+			default: NOT_REACHED();
+		}
+	}
+
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
+	{
+		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
+	}
+
+	virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number)
+	{
+		Point pt = GetToolbarAlignedWindowPosition(sm_width);
+		pt.y += sm_height;
+		return pt;
+	}
+
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+	{
+		if (pt.x != -1) {
+			switch (select_proc) {
+				default: NOT_REACHED();
+				case DDSP_DEMOLISH_AREA:
+					GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
+					break;
+			}
+		}
+	}
+
+	virtual void OnPlaceObjectAbort()
+	{
+		DeleteWindowById(WC_BUILD_OBJECT, 0);
+		this->RaiseButtons();
+	}
+
+	static HotkeyList hotkeys;
+};
+
+/**
+ * Handler for global hotkeys of the UndergroundToolbarWindow.
+ * @param hotkey Hotkey
+ * @return ES_HANDLED if hotkey was accepted.
+ */
+static EventState UndergroundToolbarGlobalHotkeys(int hotkey)
+{
+       if (_game_mode != GM_NORMAL) return ES_NOT_HANDLED;
+/* TODO       Window *w = ShowAIDebugWindow(INVALID_COMPANY);
+       if (w == NULL) return ES_NOT_HANDLED;
+       return w->OnHotkey(hotkey); */
+}
+
+EventState UndergroundToolbarGlobalHotkeys(uint16 key, uint16 keycode)
+{
+/*	int num = CheckHotkeyMatch<UndergroundToolbarWindow>(_underground_hotkeys, keycode, NULL, true);
+	if (num == -1) return ES_NOT_HANDLED;
+	Window *w = ShowUndergroundToolbar(NULL);  TODO
+	if (w == NULL) return ES_NOT_HANDLED;
+	return w->OnKeyPress(key, keycode);
+}
+		int num = CheckHotkeyMatch(underground_hotkeys, keycode, this);
+		if (num == -1) return ES_NOT_HANDLED;
+		this->OnClick(Point(), num, 1);
+		return ES_HANDLED;
++static EventState AIDebugGlobalHotkeys(int hotkey)
++{
++       if (_game_mode != GM_NORMAL) return ES_NOT_HANDLED;
++       Window *w = ShowAIDebugWindow(INVALID_COMPANY);
++       if (w == NULL) return ES_NOT_HANDLED;
++       return w->OnHotkey(hotkey);
++}
+-EventState AIDebugGlobalHotkeys(uint16 key, uint16 keycode)
+-{
+-       int num = CheckHotkeyMatch<AIDebugWindow>(_aidebug_hotkeys, keycode, NULL, true);
+-       if (num == -1) return ES_NOT_HANDLED;
+-       Window *w = ShowAIDebugWindow(INVALID_COMPANY);
+-       if (w == NULL) return ES_NOT_HANDLED;
+-       return w->OnKeyPress(key, keycode);
+-}
+- */
+  return ES_NOT_HANDLED;
+}
+
+static Hotkey underground_hotkeys[] = {
+	Hotkey('D' | WKC_GLOBAL_HOTKEY, "dynamite", WID_UT_DEMOLISH),
+	Hotkey('0', "placeescalator", WID_UT_BUILD_ESCALATOR),
+	HOTKEY_LIST_END
+};
+HotkeyList UndergroundToolbarWindow::hotkeys("undergroundtoolbar", underground_hotkeys, UndergroundToolbarGlobalHotkeys);
+
+static const NWidgetPart _nested_underground_widgets[] = {
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
+		NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_UNDERGROUND_BUILD, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
+		NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
+	EndContainer(),
+	NWidget(NWID_HORIZONTAL),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_UT_BUILD_ESCALATOR),
+						SetFill(0, 1), SetMinimalSize(42, 22), SetDataTip(SPR_IMG_RAIL_STATION, STR_UNDERGROUND_TOOLTIP_ESCALATOR),
+		NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(64, 22), EndContainer(),
+		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_UT_DEMOLISH), SetMinimalSize(22, 22),
+						SetFill(0, 1), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
+	EndContainer(),
+};
+
+static WindowDesc _underground_desc(
+	WDP_MANUAL, "undergroundtoolbar", 0, 0,
+	WC_UNDERGROUND, WC_NONE,
+	WDF_CONSTRUCTION,
+	_nested_underground_widgets, lengthof(_nested_underground_widgets)
+);
+
+/**
+ * Show the toolbar for terraforming in the game.
+ * @param link The toolbar we might want to link to.
+ * @return The allocated toolbar.
+ */
+Window *ShowUndergroundToolbar(Window *link)
+{
+	if (!Company::IsValidID(_local_company)) return NULL;
+
+	Window *w;
+	if (link == NULL) {
+		w = AllocateWindowDescFront<UndergroundToolbarWindow>(&_underground_desc, 0);
+		return w;
+	}
+
+	/* Delete the terraform toolbar to place it again. */
+	DeleteWindowById(WC_UNDERGROUND, 0, true);
+	w = AllocateWindowDescFront<UndergroundToolbarWindow>(&_underground_desc, 0);
+	/* Align the terraform toolbar under the main toolbar. */
+	w->top -= w->height;
+	w->SetDirty();
+	/* Put the linked toolbar to the left / right of it. */
+	link->left = w->left + (_current_text_dir == TD_RTL ? w->width : -link->width);
+	link->top  = w->top;
+	link->SetDirty();
+
+	return w;
+}
diff --git a/src/underground_gui.h b/src/underground_gui.h
new file mode 100644
index 00000000000..81b119545ec
--- /dev/null
+++ b/src/underground_gui.h
@@ -0,0 +1,19 @@
+/* $Id: underground_gui.h 21608 2012-09-08 1:13:14 constructor $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file underground_gui.h GUI stuff related to terraforming. */
+
+#ifndef UNDERGROUND_GUI_H
+#define UNDERGROUND_GUI_H
+
+#include "window_type.h"
+
+Window *ShowUndergroundToolbar(Window *link = NULL);
+
+#endif /* UNDERGROUND_GUI_H */
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index a458b1c6502..f932e33bd89 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -13,6 +13,7 @@
 #include "ship.h"
 #include "spritecache.h"
 #include "timetable.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "news_func.h"
 #include "command_func.h"
@@ -1138,6 +1139,7 @@ void ViewportAddVehicles(DrawPixelInfo *dpi)
 			const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF
 
 			while (v != nullptr) {
+				if (LayerIndex(v->tile) == dpi->layer)
 				if (!(v->vehstatus & VS_HIDDEN) &&
 						l <= v->coord.right &&
 						t <= v->coord.bottom &&
diff --git a/src/viewport.cpp b/src/viewport.cpp
index e28a2e606e6..7398d335e04 100644
--- a/src/viewport.cpp
+++ b/src/viewport.cpp
@@ -62,6 +62,8 @@
 
 #include "stdafx.h"
 #include "landscape.h"
+#include "layer_gui.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "station_base.h"
 #include "waypoint_base.h"
@@ -1244,24 +1246,27 @@ static void ViewportAddLandscape()
 			int min_visible_height = viewport_y - (_vd.dpi.top + _vd.dpi.height);
 			bool tile_visible = min_visible_height <= 0;
 
-			if (tile_type != MP_VOID) {
-				/* Is tile with buildings visible? */
-				if (min_visible_height < MAX_TILE_EXTENT_TOP) tile_visible = true;
-
-				if (IsBridgeAbove(tile_info.tile)) {
-					/* Is the bridge visible? */
-					TileIndex bridge_tile = GetNorthernBridgeEnd(tile_info.tile);
-					int bridge_height = ZOOM_LVL_BASE * (GetBridgePixelHeight(bridge_tile) - TilePixelHeight(tile_info.tile));
-					if (min_visible_height < bridge_height + MAX_TILE_EXTENT_TOP) tile_visible = true;
-				}
+			/*	������� ������ ������ �������� ����	*/
+			if (LayerIndex(tile_info.tile) == _vd.dpi.layer) {
+				if (tile_type != MP_VOID) {
+					/* Is tile with buildings visible? */
+					if (min_visible_height < MAX_TILE_EXTENT_TOP) tile_visible = true;
+
+					if (IsBridgeAbove(tile_info.tile)) {
+						/* Is the bridge visible? */
+						TileIndex bridge_tile = GetNorthernBridgeEnd(tile_info.tile);
+						int bridge_height = ZOOM_LVL_BASE * (GetBridgePixelHeight(bridge_tile) - TilePixelHeight(tile_info.tile));
+						if (min_visible_height < bridge_height + MAX_TILE_EXTENT_TOP) tile_visible = true;
+					}
 
-				/* Would a higher bridge on a more southern tile be visible?
-				 * If yes, we need to loop over more rows to possibly find one. */
-				if (min_visible_height < potential_bridge_height + MAX_TILE_EXTENT_TOP) last_row = false;
-			} else {
-				/* Outside of map. If we are on the north border of the map, there may still be a bridge visible,
-				 * so we need to loop over more rows to possibly find one. */
-				if ((tilecoord.x <= 0 || tilecoord.y <= 0) && min_visible_height < potential_bridge_height + MAX_TILE_EXTENT_TOP) last_row = false;
+					/* Would a higher bridge on a more southern tile be visible?
+					 * If yes, we need to loop over more rows to possibly find one. */
+					if (min_visible_height < potential_bridge_height + MAX_TILE_EXTENT_TOP) last_row = false;
+				} else {
+					/* Outside of map. If we are on the north border of the map, there may still be a bridge visible,
+					 * so we need to loop over more rows to possibly find one. */
+					if ((tilecoord.x <= 0 || tilecoord.y <= 0) && min_visible_height < potential_bridge_height + MAX_TILE_EXTENT_TOP) last_row = false;
+				}
 			}
 
 			if (tile_visible) {
@@ -1673,6 +1678,9 @@ void ViewportDoDraw(const Viewport *vp, int left, int top, int right, int bottom
 
 	_vd.dpi.dst_ptr = BlitterFactory::GetCurrentBlitter()->MoveTo(old_dpi->dst_ptr, x - old_dpi->left, y - old_dpi->top);
 
+	/*	����������� ���� (������� ����� ��������)	*/
+	_vd.dpi.layer = calculateLayer(vp);
+
 	ViewportAddLandscape();
 	ViewportAddVehicles(&_vd.dpi);
 
diff --git a/src/viewport_func.h b/src/viewport_func.h
index 466a24a3b3f..5aca63aee43 100644
--- a/src/viewport_func.h
+++ b/src/viewport_func.h
@@ -31,6 +31,7 @@ void MarkAllViewportsDirty(int left, int top, int right, int bottom);
 
 bool DoZoomInOutWindow(ZoomStateChange how, Window *w);
 void ZoomInOrOutToCursorWindow(bool in, Window * w);
+void LayerUpOrDownToCursorWindow(bool in, Window * w);
 Point GetTileZoomCenterWindow(bool in, Window * w);
 void FixTitleGameZoom();
 void HandleZoomMessage(Window *w, const Viewport *vp, byte widget_zoom_in, byte widget_zoom_out);
diff --git a/src/viewport_gui.cpp b/src/viewport_gui.cpp
index 5047f04f3f4..3c02f9ab8bb 100644
--- a/src/viewport_gui.cpp
+++ b/src/viewport_gui.cpp
@@ -14,6 +14,7 @@
 #include "strings_func.h"
 #include "zoom_func.h"
 #include "window_func.h"
+#include "gfx_func.h"
 
 #include "widgets/viewport_widget.h"
 
@@ -137,7 +138,11 @@ public:
 	void OnMouseWheel(int wheel) override
 	{
 		if (_settings_client.gui.scrollwheel_scrolling != 2) {
-			ZoomInOrOutToCursorWindow(wheel < 0, this);
+			if (_ctrl_pressed) {
+				LayerUpOrDownToCursorWindow(wheel < 0, this);
+			} else {
+				ZoomInOrOutToCursorWindow(wheel < 0, this);
+			}
 		}
 	}
 
diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp
index 5e37c16dd77..29541fb72d0 100644
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -10,6 +10,7 @@
 #include "stdafx.h"
 #include "cmd_helper.h"
 #include "landscape.h"
+#include "layer_func.h"
 #include "viewport_func.h"
 #include "command_func.h"
 #include "town.h"
@@ -466,6 +467,11 @@ CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
 		/* can't make water of water! */
 		if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue;
 
+               /* can't make underground water  */
+               if (IsUnderground(tile)) {
+                       return_cmd_error(STR_ERROR_UNDERGROUND_CAN_T_BUILD_UNDER_GROUND);
+               }
+
 		bool water = IsWaterTile(tile);
 		ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR);
 		if (ret.Failed()) return ret;
@@ -1097,6 +1103,9 @@ void DoFloodTile(TileIndex target)
 {
 	assert(!IsTileType(target, MP_WATER));
 
+	/*	��������� ����� ����� �� ����������	*/
+	if (IsUnderground(target)) return;
+
 	bool flooded = false; // Will be set to true if something is changed.
 
 	Backup<CompanyID> cur_company(_current_company, OWNER_WATER, FILE_LINE);
@@ -1256,7 +1265,7 @@ void ConvertGroundTilesIntoWaterTiles()
 
 	for (TileIndex tile = 0; tile < MapSize(); ++tile) {
 		Slope slope = GetTileSlope(tile, &z);
-		if (IsTileType(tile, MP_CLEAR) && z == 0) {
+		if (IsTileType(tile, MP_CLEAR) && z == 0 && !IsUnderground(tile)) {
 			/* Make both water for tiles at level 0
 			 * and make shore, as that looks much better
 			 * during the generation. */
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
index 18ecd529e84..509adda5810 100644
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -55,6 +55,7 @@ add_files(
     town_widget.h
     transparency_widget.h
     tree_widget.h
+    underground_widget.h
     vehicle_widget.h
     viewport_widget.h
     waypoint_widget.h
diff --git a/src/widgets/genworld_widget.h b/src/widgets/genworld_widget.h
index f7bf20e950c..f7af296f607 100644
--- a/src/widgets/genworld_widget.h
+++ b/src/widgets/genworld_widget.h
@@ -19,6 +19,7 @@ enum GenerateLandscapeWidgets {
 
 	WID_GL_MAPSIZE_X_PULLDOWN,          ///< Dropdown 'map X size'.
 	WID_GL_MAPSIZE_Y_PULLDOWN,          ///< Dropdown 'map Y size'.
+	WID_GL_LAYER_COUNT_PULLDOWN,        ///< Dropdown 'map layer count'.
 
 	WID_GL_TOWN_PULLDOWN,               ///< Dropdown 'No. of towns'.
 	WID_GL_INDUSTRY_PULLDOWN,           ///< Dropdown 'No. of industries'.
@@ -67,6 +68,7 @@ enum CreateScenarioWidgets {
 	WID_CS_RANDOM_WORLD,           ///< Generate random land button
 	WID_CS_MAPSIZE_X_PULLDOWN,     ///< Pull-down arrow for x map size.
 	WID_CS_MAPSIZE_Y_PULLDOWN,     ///< Pull-down arrow for y map size.
+	WID_CS_LAYER_COUNT_PULLDOWN,   ///< Pull-down arrow for map layer count.
 	WID_CS_START_DATE_DOWN,        ///< Decrease start year (start earlier).
 	WID_CS_START_DATE_TEXT,        ///< Clickable start date value.
 	WID_CS_START_DATE_UP,          ///< Increase start year (start later).
diff --git a/src/widgets/toolbar_widget.h b/src/widgets/toolbar_widget.h
index d68de497004..0b4e53227f4 100644
--- a/src/widgets/toolbar_widget.h
+++ b/src/widgets/toolbar_widget.h
@@ -41,6 +41,7 @@ enum ToolbarNormalWidgets {
 	WID_TN_WATER,         ///< Water building toolbar.
 	WID_TN_AIR,           ///< Airport building toolbar.
 	WID_TN_LANDSCAPE,     ///< Landscaping toolbar.
+	WID_TN_UNDERGROUND,   ///< Landscaping toolbar.
 	WID_TN_MUSIC_SOUND,   ///< Music/sound configuration menu.
 	WID_TN_MESSAGES,      ///< Messages menu.
 	WID_TN_HELP,          ///< Help menu.
diff --git a/src/widgets/underground_widget.h b/src/widgets/underground_widget.h
new file mode 100644
index 00000000000..522c9db8bf2
--- /dev/null
+++ b/src/widgets/underground_widget.h
@@ -0,0 +1,21 @@
+/* $Id: terraform_widget.h 23600 2011-12-19 20:46:17Z truebrain $ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file terraform_widget.h Types related to the terraform widgets. */
+
+#ifndef WIDGETS_UNDERGROUND_WIDGET_H
+#define WIDGETS_UNDERGROUND_WIDGET_H
+
+/** Widgets of the #TerraformToolbarWindow class. */
+enum UndergroundToolbarWidgets {
+	WID_UT_BUILD_ESCALATOR,					  ///< Build escalator
+	WID_UT_DEMOLISH,                          ///< Demolish aka dynamite button.
+};
+
+#endif /* WIDGETS_UNDERGROUND_WIDGET_H */
diff --git a/src/window_type.h b/src/window_type.h
index 86dcc6fb335..02533dd0308 100644
--- a/src/window_type.h
+++ b/src/window_type.h
@@ -441,6 +441,12 @@ enum WindowClass {
 	 */
 	WC_SCEN_LAND_GEN,
 
+	/**
+	 * Underground (in game); %Window numbers:
+	 *   - 0 = #UndergroundToolbarWidgets
+	 */
+	WC_UNDERGROUND,
+
 	/**
 	 * Generate landscape (newgame); %Window numbers:
 	 *   - GLWM_SCENARIO = #CreateScenarioWidgets