diff --git a/src/simutrans/builder/wegbauer.cc b/src/simutrans/builder/wegbauer.cc
index 66265f3da..3a5736869 100644
--- a/src/simutrans/builder/wegbauer.cc
+++ b/src/simutrans/builder/wegbauer.cc
@@ -121,8 +121,9 @@ bool way_builder_t::register_desc(way_desc_t *desc)
 	}
 
 	if(  desc->get_cursor()->get_image_id(1)!=IMG_EMPTY  ) {
-		// add the tool
-		tool_build_way_t *tool = new tool_build_way_t();
+		// add the tool; an elevated way gets its own one, so that a pakset does not have to
+		// name a different tool in its menuconf.tab to keep them apart
+		tool_build_way_t *tool = tool_build_way_t::is_elevated_desc(desc) ? new tool_build_elevated_way_t() : new tool_build_way_t();
 		tool->set_icon( desc->get_cursor()->get_image_id(1) );
 		tool->cursor = desc->get_cursor()->get_image_id(0);
 		tool->set_default_param(desc->get_name());
diff --git a/src/simutrans/network/network_cmd_ingame.cc b/src/simutrans/network/network_cmd_ingame.cc
index 39ccbc775..22cc20fa3 100644
--- a/src/simutrans/network/network_cmd_ingame.cc
+++ b/src/simutrans/network/network_cmd_ingame.cc
@@ -1149,7 +1149,8 @@ void nwc_tool_t::init_tool()
 	// create new memory_rw_t that is in reading mode to read tool data
 	memory_rw_t new_custom_data(custom_data_buf, custom_data.get_current_index(), false);
 
-	if ( (tool = create_tool(tool_id)) ) {
+	// the parameter is given to the factory too, so that both sides build the same tool
+	if ( (tool = create_tool(tool_id, default_param)) ) {
 		tool->set_default_param(default_param);
 		tool->rdwr_custom_data(&new_custom_data);
 	}
diff --git a/src/simutrans/script/api/api_command.cc b/src/simutrans/script/api/api_command.cc
index 4f1aaa390..a5099d38e 100644
--- a/src/simutrans/script/api/api_command.cc
+++ b/src/simutrans/script/api/api_command.cc
@@ -182,7 +182,7 @@ SQInteger command_work(HSQUIRRELVM vm)
 
 tool_t * call_tool_base_t::create_tool()
 {
-	tool_t *tool = ::create_tool(tool_id);
+	tool_t *tool = ::create_tool(tool_id, default_param);
 	if (tool) {
 		tool->set_default_param(default_param);
 		tool->flags = flags;
diff --git a/src/simutrans/tool/simmenu.cc b/src/simutrans/tool/simmenu.cc
index 8f219db4f..a448e8d43 100644
--- a/src/simutrans/tool/simmenu.cc
+++ b/src/simutrans/tool/simmenu.cc
@@ -231,7 +231,22 @@ public:
 };
 tool_t* tool_t::dummy = new tool_dummy_t();
 
-tool_t* create_general_tool(int toolnr)
+/**
+ * Elevated ways are built by their own tool. Only the parameter is known here, so one that
+ * names no way - a way type number, or a name with the automatic suffix - gives the general
+ * tool, which still builds an elevated way from the descriptor it finds later.
+ */
+static tool_t* create_way_tool(const char* param)
+{
+	const way_desc_t* desc = param ? way_builder_t::get_desc(param) : NULL;
+	if (tool_build_way_t::is_elevated_desc(desc)) {
+		return new tool_build_elevated_way_t();
+	}
+	return new tool_build_way_t();
+}
+
+
+tool_t* create_general_tool(int toolnr, const char* param)
 {
 	tool_t* tool = NULL;
 	switch (toolnr) {
@@ -249,7 +264,7 @@ tool_t* create_general_tool(int toolnr)
 	case TOOL_PLANT_TREE:                  tool = new tool_plant_tree_t();          break;
 	case TOOL_SCHEDULE_ADD:                tool = new tool_schedule_add_t();        break;
 	case TOOL_SCHEDULE_INS:                tool = new tool_schedule_ins_t();        break;
-	case TOOL_BUILD_WAY:                   tool = new tool_build_way_t();           break;
+	case TOOL_BUILD_WAY:                   tool = create_way_tool(param);           break;
 	case TOOL_BUILD_BRIDGE:                tool = new tool_build_bridge_t();        break;
 	case TOOL_BUILD_TUNNEL:                tool = new tool_build_tunnel_t();        break;
 	case TOOL_WAYREMOVER:                  tool = new tool_wayremover_t();          break;
@@ -409,11 +424,11 @@ tool_t* create_dialog_tool(int toolnr)
 	return tool;
 }
 
-tool_t* create_tool(int toolnr)
+tool_t* create_tool(int toolnr, const char* param)
 {
 	tool_t* tool = NULL;
 	if (toolnr & GENERAL_TOOL) {
-		tool = create_general_tool(toolnr & 0xFFF);
+		tool = create_general_tool(toolnr & 0xFFF, param);
 	}
 	else if (toolnr & SIMPLE_TOOL) {
 		tool = create_simple_tool(toolnr & 0xFFF);
@@ -622,7 +637,7 @@ static utf32 str_to_key(const char* str, uint8* modifier)
 void tool_t::init_menu()
 {
 	for (uint16 i = 0; i < GENERAL_TOOL_COUNT; i++) {
-		tool_t* tool = create_general_tool(i);
+		tool_t* tool = create_general_tool(i, NULL);
 		general_tool.append(tool);
 	}
 	for (uint16 i = 0; i < SIMPLE_TOOL_COUNT; i++) {
@@ -891,7 +906,7 @@ bool tool_t::read_menu(const std::string& menuconf_path)
 							dbg->warning("tool_t::read_menu()", "toolbar[%i][%i]: replaced way-builder(id=14) with default param=cityroad by cityroad builder(id=36)", i, j);
 						}
 						// now create tool
-						addtool = create_general_tool(toolnr);
+						addtool = create_general_tool(toolnr, param_str);
 						// copy defaults
 						*addtool = *(general_tool[toolnr]);
 						set_defaults_general_tool(addtool, param_str);
diff --git a/src/simutrans/tool/simmenu.h b/src/simutrans/tool/simmenu.h
index 756b41cf1..926961c1c 100644
--- a/src/simutrans/tool/simmenu.h
+++ b/src/simutrans/tool/simmenu.h
@@ -502,7 +502,7 @@ public:
 	void clear();
 };
 
-// create new instance of tool
-tool_t *create_tool(int toolnr);
+// create new instance of tool; the parameter picks the tool of a way when it names one
+tool_t *create_tool(int toolnr, const char *param = NULL);
 
 #endif
diff --git a/src/simutrans/tool/simtool.cc b/src/simutrans/tool/simtool.cc
index 48220b45c..254a55abb 100644
--- a/src/simutrans/tool/simtool.cc
+++ b/src/simutrans/tool/simtool.cc
@@ -2605,6 +2605,19 @@ const way_desc_t *tool_build_way_t::get_desc() const
 	return desc;
 }
 
+bool tool_build_way_t::is_elevated_desc(const way_desc_t *desc)
+{
+	// an air way with the same system type is a runway, and that one stays on the ground
+	return desc  &&  desc->get_styp() == type_elevated  &&  desc->get_wtyp() != air_wt;
+}
+
+
+bool tool_build_way_t::is_elevated() const
+{
+	return is_elevated_desc(desc);
+}
+
+
 const way_desc_t* tool_build_way_t::get_default_desc(waytype_t wt)
 {
 	const way_desc_t* desc;
@@ -2725,7 +2738,7 @@ waytype_t tool_build_way_t::get_waytype() const
 
 void tool_build_way_t::start_at( koord3d &new_start )
 {
-	if(  is_shift_pressed()  &&  (desc->get_styp() == type_elevated  &&  desc->get_wtyp() != air_wt)  ) {
+	if(  is_shift_pressed()  &&  is_elevated()  ) {
 		grund_t *gr=welt->lookup(new_start);
 		if(  gr->get_weg( desc->get_waytype() )  ) {
 			new_start.z -= welt->get_settings().get_way_height_clearance();
@@ -2744,7 +2757,7 @@ uint8 tool_build_way_t::is_valid_pos( player_t *player, const koord3d &pos, cons
 		if(  gr->get_typ() == grund_t::tunnelboden  &&  !gr->ist_karten_boden()  && !(desc->is_tram()  && !gr->hat_weg(water_wt)) ) {
 			return 0;
 		}
-		bool const elevated = desc->get_styp() == type_elevated  &&  desc->get_wtyp() != air_wt;
+		bool const elevated = is_elevated();
 		// ignore water
 		if(  desc->get_wtyp() != water_wt  &&  gr->get_typ() == grund_t::wasser  ) {
 			if(  !elevated  ||  welt->lookup_hgt( pos.get_2d() ) < welt->get_water_hgt( pos.get_2d() )  ) {
@@ -2800,7 +2813,7 @@ const char *tool_build_way_t::calc_route( way_builder_t &bauigel, const koord3d
 		bautyp = way_builder_t::schiene_tram;
 	}
 	// elevated track?
-	if(desc->get_styp()==type_elevated  &&  desc->get_wtyp()!=air_wt) {
+	if(  is_elevated()  ) {
 		bautyp |= way_builder_t::elevated_flag;
 	}
 	const tunnel_desc_t* tunnel = NULL;
@@ -2827,7 +2840,7 @@ const char *tool_build_way_t::calc_route( way_builder_t &bauigel, const koord3d
 
 	koord3d my_end = end;
 	// ending point is applied that elevated ways with SHIFT selects the current layer, when already on an elevated way
-	if(  is_shift_pressed()  &&  (desc->get_styp() == type_elevated  &&  desc->get_wtyp() != air_wt)  ) {
+	if(  is_shift_pressed()  &&  is_elevated()  ) {
 		grund_t *gr=welt->lookup(my_end);
 		if(  gr->get_weg( desc->get_waytype() )  ) {
 			// find the base ground this elevated way was built above; this accounts for the
@@ -2935,8 +2948,8 @@ void tool_build_way_t::mark_tiles(player_t* player, const koord3d& start, const
 	const char* err = calc_route(bauigel, start, end);
 	bool keep_city_roads = is_shift_pressed() && desc->get_styp() == type_flat && desc->get_wtyp() == road_wt;
 
-	bool is_elevated = desc->get_styp() == type_elevated && desc->get_wtyp() != air_wt;
-	uint8 offset = is_elevated ? welt->get_settings().get_way_height_clearance() : 0;
+	bool elevated = is_elevated();
+	uint8 offset = elevated ? welt->get_settings().get_way_height_clearance() : 0;
 
 	if (bauigel.get_count() > 1) {
 		// Set tooltip first (no dummygrounds, if bauigel.calc_casts() is called).
@@ -2946,7 +2959,7 @@ void tool_build_way_t::mark_tiles(player_t* player, const koord3d& start, const
 		for (uint32 j = 0; j < bauigel.get_count(); j++) {
 			koord3d base_pos = bauigel.get_route()[j];
 			grund_t* base_gr = welt->lookup(base_pos);
-			sint8 extra_h = (is_elevated && base_gr) ? base_gr->get_bridge_slope_extra_height() : 0;
+			sint8 extra_h = (elevated && base_gr) ? base_gr->get_bridge_slope_extra_height() : 0;
 			koord3d pos = base_pos + koord3d(0, 0, offset + extra_h);
 			grund_t* gr = welt->lookup(pos);
 			if (!gr) {
diff --git a/src/simutrans/tool/simtool.h b/src/simutrans/tool/simtool.h
index 08e3dc40c..d92987286 100644
--- a/src/simutrans/tool/simtool.h
+++ b/src/simutrans/tool/simtool.h
@@ -304,6 +304,7 @@ protected:
 	virtual way_desc_t const* get_desc() const;
 	const char *calc_route( way_builder_t &bauigel, const koord3d &, const koord3d & );
 	void start_at( koord3d &new_start ) OVERRIDE;
+	virtual bool is_elevated() const;
 
 public:
 	tool_build_way_t(uint16 const id = TOOL_BUILD_WAY | GENERAL_TOOL) : two_click_tool_t(id), desc() {
@@ -312,6 +313,8 @@ public:
 	}
 	image_id get_icon(player_t*) const OVERRIDE;
 	static const way_desc_t* get_default_desc(waytype_t wt);
+	// which descriptors are built on their own level above the ground
+	static bool is_elevated_desc(const way_desc_t *desc);
 	char const* get_tooltip(player_t const*) const OVERRIDE;
 	char const* get_default_param(player_t*) const OVERRIDE;
 	bool is_selected() const OVERRIDE;
@@ -319,7 +322,17 @@ public:
 	bool is_init_keeps_game_state() const OVERRIDE { return true; }
 	waytype_t get_waytype() const OVERRIDE;
 	// remove preview necessary while building elevated ways
-	bool remove_preview_necessary() const OVERRIDE { return !is_first_click()  &&  (desc  &&  (desc->get_styp() == type_elevated  &&  desc->get_wtyp() != air_wt)); }
+	bool remove_preview_necessary() const OVERRIDE { return !is_first_click()  &&  is_elevated(); }
+};
+
+/**
+ * Ways built on their own level above the ground. An elevated descriptor is given this tool
+ * instead of the normal one wherever the descriptor is known. The base class still decides
+ * from the descriptor, so a way that ends up with the general tool is built the same way.
+ */
+class tool_build_elevated_way_t : public tool_build_way_t {
+protected:
+	bool is_elevated() const OVERRIDE { return true; }
 };
 
 class tool_build_cityroad : public tool_build_way_t {
