diff --git src/simutrans/tool/simmenu.cc src/simutrans/tool/simmenu.cc
index 7a6ef62222..e4ab0c0097 100644
--- src/simutrans/tool/simmenu.cc
+++ src/simutrans/tool/simmenu.cc
@@ -119,6 +119,8 @@ const char *tool_t::id_to_string(uint16 id)
 		CASE_TO_STRING(TOOL_EXEC_TWO_CLICK_SCRIPT);
 		CASE_TO_STRING(TOOL_PLANT_GROUNDOBJ);
 		CASE_TO_STRING(TOOL_ADD_MESSAGE);
+		CASE_TO_STRING(TOOL_REMOVE_SIGNAL);
+		CASE_TO_STRING(TOOL_PIPETTE);
 		}
 	}
 	else if (id & SIMPLE_TOOL) {
@@ -271,6 +273,7 @@ tool_t *create_general_tool(int toolnr)
 		case TOOL_PLANT_GROUNDOBJ:             tool = new tool_plant_groundobj_t();     break;
 		case TOOL_ADD_MESSAGE:                 tool = new tool_add_message_t();         break;
 		case TOOL_REMOVE_SIGNAL:               tool = new tool_remove_signal_t();       break;
+		case TOOL_PIPETTE:                     tool = new tool_pipette_t();             break;
 		default:
 			dbg->error("create_general_tool()","cannot satisfy request for general_tool[%i]!",toolnr);
 			return NULL;
diff --git src/simutrans/tool/simmenu.h src/simutrans/tool/simmenu.h
index 488c4938fa..b95dedc6a6 100644
--- src/simutrans/tool/simmenu.h
+++ src/simutrans/tool/simmenu.h
@@ -79,6 +79,7 @@ enum {
 	TOOL_PLANT_GROUNDOBJ,
 	TOOL_ADD_MESSAGE,
 	TOOL_REMOVE_SIGNAL,
+	TOOL_PIPETTE,
 	GENERAL_TOOL_COUNT,
 	GENERAL_TOOL = 0x1000
 };
diff --git src/simutrans/tool/simtool.cc src/simutrans/tool/simtool.cc
index 04adade578..bed1ee2f20 100644
--- src/simutrans/tool/simtool.cc
+++ src/simutrans/tool/simtool.cc
@@ -6784,7 +6784,7 @@ const char *tool_merge_stop_t::do_work( player_t *player, const koord3d &last_po
 }
 
 
-const char* tool_remove_signal_t::work( player_t* player, koord3d pos )
+const char *tool_remove_signal_t::work( player_t* player, koord3d pos )
 {
 	if(  grund_t *gr=welt->lookup(pos)  ) {
 		if(  signal_t *rs=gr->find<signal_t>()  ) {
@@ -6816,6 +6816,88 @@ const char* tool_remove_signal_t::work( player_t* player, koord3d pos )
 }
 
 
+const char *tool_pipette_t::work(player_t *pl, koord3d pos)
+{
+	const grund_t *gr = welt->lookup(pos);
+	if (!gr) {
+		return NULL;
+	}
+
+	if (tunnel_t *tunnel = gr->find<tunnel_t>()) {
+		welt->set_tool(tunnel->get_desc()->get_builder(), pl);
+		return NULL;
+	}
+	else if (bruecke_t *bridge = gr->find<bruecke_t>()) {
+		welt->set_tool(bridge->get_desc()->get_builder(), pl);
+		return NULL;
+	}
+
+	if (gr->get_flag(grund_t::has_way1)) {
+		// depots > stops > signals > wayobjs > ways
+		if (gebaeude_t *building = select_depot_or_station(gr, pl)) {
+			welt->set_tool(building->get_tile()->get_desc()->get_builder(), pl);
+			return NULL;
+		}
+		else if (roadsign_t *sign = select_sign(gr, pl)) {
+			welt->set_tool(sign->get_desc()->get_builder(), pl);
+			return NULL;
+		}
+		else if (wayobj_t *wo = gr->find<wayobj_t>()) {
+			welt->set_tool(wo->get_desc()->get_builder(), pl);
+			return NULL;
+		}
+		else if (tool_t *way_builder = gr->get_weg_nr(0)->get_desc()->get_builder()) {
+			welt->set_tool(way_builder, pl);
+			return NULL;
+		}
+	}
+	else if (gebaeude_t *gb = gr->find<gebaeude_t>()) {
+		const building_desc_t *desc = gb->get_tile()->get_desc();
+		if (desc->is_transport_building() && desc->is_available(welt->get_timeline_year_month()) && desc->get_builder()) {
+			welt->set_tool(desc->get_builder(), pl);
+			return NULL;
+		}
+	}
+	else if (leitung_t *lt = gr->find<leitung_t>()) {
+		welt->set_tool(lt->get_desc()->get_builder(), pl);
+		return NULL;
+	}
+	else if (gr->find<senke_t>() || gr->find<pumpe_t>()) {
+		welt->set_tool(tool_t::general_tool[TOOL_TRANSFORMER], pl);
+		return NULL;
+	}
+
+	return NULL;
+}
+
+
+gebaeude_t *tool_pipette_t::select_depot_or_station(const grund_t *gr, const player_t *owner)
+{
+	if (depot_t *dep = gr->get_depot()) {
+		// public player cannot build depots
+		return owner != welt->get_public_player() ? dep : NULL;
+	}
+	else if (gebaeude_t *gb = gr->find<gebaeude_t>()) {
+		return gb;
+	}
+
+	return NULL;
+}
+
+
+roadsign_t *tool_pipette_t::select_sign(const grund_t *gr, const player_t* owner)
+{
+	if (signal_t *signal = gr->find<signal_t>()) {
+		return signal;
+	}
+	else if (roadsign_t *rs = gr->find<roadsign_t>()) {
+		return rs;
+	}
+
+	return NULL;
+}
+
+
 bool tool_show_trees_t::init( player_t* )
 {
 	env_t::hide_trees = !env_t::hide_trees;
diff --git src/simutrans/tool/simtool.h src/simutrans/tool/simtool.h
index 474f972342..9644fe683b 100644
--- src/simutrans/tool/simtool.h
+++ src/simutrans/tool/simtool.h
@@ -662,6 +662,24 @@ public:
 };
 
 
+// Copies item under cursor into cursor
+class tool_pipette_t : public tool_t
+{
+public:
+	tool_pipette_t() : tool_t(TOOL_PIPETTE | GENERAL_TOOL) {}
+
+public:
+	const char *get_tooltip(const player_t *) const OVERRIDE { return translator::translate("Pipette"); }
+	const char *work(player_t *, koord3d) OVERRIDE;
+	bool is_init_keeps_game_state() const OVERRIDE { return true; }
+	bool is_work_keeps_game_state() const OVERRIDE { return true; }
+
+private:
+	roadsign_t *select_sign(const grund_t *gr, const player_t *owner);
+	gebaeude_t *select_depot_or_station(const grund_t *gr, const player_t *owner);
+};
+
+
 // internal tool: show error message at specific coordinate
 // used for scenario error messages send by server
 class tool_error_message_t : public tool_t {
