The International Simutrans Forum

Development => Patches & Projects => Incorporated Patches and Solved Bug Reports => Topic started by: poppo on February 13, 2026, 09:29:40 AM

Title: pipette tool update request: pick way, pick tram-way
Post by: poppo on February 13, 2026, 09:29:40 AM
Pipette tool is one of the wonderful tool to build!
However, we pick only the surface object, so we cannot get object at the base of each ground, especially way or tram-way.
So, I request 2 things:
when we press both ctrl and shift, we can get way_nr(1)'s way.

If you want to test this tool-request, please play OTRPatch v51_2 https://github.com/teamhimeh/simutrans/releases/tag/v51_2
Title: Re: pipette tool update request: pick way, pick tram-way
Post by: Yona-TYT on February 18, 2026, 09:13:48 PM
It's strange that @prissi didn't reply to this post, perhaps she didn't see it. I hope this message serves as a reminder.  ;)
Title: Re: pipette tool update request: pick way, pick tram-way
Post by: prissi on February 19, 2026, 12:54:00 PM
There was no patch and I am very stressed with other things right now. Such an expert feature can go in, but I will not dig out the code for that
Title: Re: pipette tool update request: pick way, pick tram-way
Post by: poppo on February 25, 2026, 05:30:33 AM
// create tool for object under the cursor
const char *tool_pipette_t::work(player_t *pl, koord3d pos)
{
    static cbuffer_t param_str;

    const grund_t *gr = welt->lookup(pos);
    if (!gr) {
        return NULL;
    }

    select_and_check(tunnel_t)
    select_and_check(bruecke_t)

    if (!gr->get_weg_nr(0)||!is_ctrl_pressed()) {
        if (gebaeude_t* gb = gr->find<gebaeude_t>()) {
            if (const char *err = allow_tool_check(gb, gb->get_tile()->get_desc(), pl)) {
                return err;
            }
            const building_desc_t* desc = gb->get_tile()->get_desc();
            if (!pl->is_public_service()) {
                // since we are not allowed to create public infrastructure as normal player, we must forbid this too
                if (desc->is_city_building()  ||  desc->is_attraction()  ||  desc->is_townhall()  ||  desc->is_monument()) {
                    return "Not allowed to copy object.";
                }
            }
            else {
                if (desc->is_depot()  ||  desc->is_headquarters()  ||  desc->is_townhall()) {
                    return "Not allowed to copy object.";
                }
            }
            // here on factories, monuments, town halls, city buildings and more
            if (gb->get_fabrik()) {
                static tool_build_factory_t t = tool_build_factory_t();
                param_str.clear();
                param_str.printf("%i%i%i,%s",
                    1, // with climate
                    gb->get_tile()->get_layout(), /*rotation*/
                    gb->get_fabrik()->get_base_production(),
                    gb->get_fabrik()->get_desc()->get_name());
                t.set_default_param(param_str);
                t.cursor = tool_t::general_tool[TOOL_BUILD_FACTORY]->cursor;
                welt->set_tool(&t, pl);
                return NULL;
            }
            else if (desc->is_attraction()  ||  desc->is_city_building()) {
                static tool_build_house_t t = tool_build_house_t();
                t.cursor = tool_t::general_tool[TOOL_BUILD_HOUSE]->cursor;
                param_str.clear();
                param_str.printf("0%d%s",
                    gb->get_tile()->get_layout(), /*rotation*/
                    gb->get_tile()->get_desc()->get_name());
                t.set_default_param(param_str);
                welt->set_tool(&t, pl);
                return NULL;
            }
            else if (tool_t* t = gb->get_tile()->get_desc()->get_builder()) {
                welt->set_tool(t, pl);
                return NULL;
            }
            return "Not allowed to copy object.";
        }
    }

    if (!is_ctrl_pressed()) {
        // we do not check depot if ctrl pressed(ctrl -> get way info directly)
        if (depot_t *depot=gr->get_depot()) {
            if (pl->is_public_service()) {
                return "Not allowed to copy object.";
            }
            tool_t* t = depot->get_tile()->get_desc()->get_builder();
            welt->set_tool(t, pl);
            return NULL;
        }
    }

    if (gr->get_weg_nr(1)&&is_shift_pressed()) {
        // we check weg_nr(1) only when shift pressed
        if(!is_ctrl_pressed()) {
            // signals > wayobjs > ways
            // if ctrl pressed, we only see way.
            select_and_check(signal_t);
            select_and_check(roadsign_t);
            if(gr->get_wayobj(gr->get_weg_nr(1)->get_waytype())){
                  if(tool_t *wayobj_builder = gr->get_wayobj(gr->get_weg_nr(1)->get_waytype())->get_desc()->get_builder()) {
                    if (const char* err = allow_tool_check(gr->get_wayobj(gr->get_weg_nr(1)->get_waytype()), gr->get_wayobj(gr->get_weg_nr(1)->get_waytype())->get_desc(), pl)) {
                        return err;
                    }
                    welt->set_tool(wayobj_builder, pl);
                    return NULL;
                }
            }
        }
        if (tool_t *way_builder = gr->get_weg_nr(1)->get_desc()->get_builder()) {
            if (const char* err = allow_tool_check(gr->get_weg_nr(1), gr->get_weg_nr(1)->get_desc(), pl)) {
                return err;
            }
            welt->set_tool(way_builder, pl);
            return NULL;
        }
        return "Not allowed to copy object.";
        // here on rivers and city roads
    }

    if (gr->get_weg_nr(0)) {
        if(!is_ctrl_pressed()) {
            // signals > wayobjs > ways
            // if ctrl pressed, we only see way.
            select_and_check(signal_t);
            select_and_check(roadsign_t);
            select_and_check(wayobj_t);
        }
        if (tool_t *way_builder = gr->get_weg_nr(0)->get_desc()->get_builder()) {
            if (const char* err = allow_tool_check(gr->get_weg_nr(0), gr->get_weg_nr(0)->get_desc(), pl)) {
                return err;
            }
            welt->set_tool(way_builder, pl);
            return NULL;
        }
        return "Not allowed to copy object.";
        // here on rivers and city roads
    }

    select_and_check(leitung_t);
    if (gr->find<senke_t>()  ||  gr->find<pumpe_t>()) {
        // missing: check for ownership
        welt->set_tool(tool_t::general_tool[TOOL_TRANSFORMER], pl);
        return NULL;
    }

    if (baum_t* b = gr->find<baum_t>()) {
        static tool_plant_tree_t t;
        param_str.clear();
        param_str.printf("%i%i,%s", 1, 0, b->get_desc()->get_name());
        t.set_default_param(param_str);
        t.cursor = tool_t::general_tool[TOOL_PLANT_TREE]->cursor;
        welt->set_tool(&t, pl);
        return NULL;
    }

    if (groundobj_t* b = gr->find<groundobj_t>()) {
        if (pl->is_public_service()) {
            static tool_plant_groundobj_t t;
            param_str.clear();
            param_str.printf("%i%i,%s", 1, 0, b->get_desc()->get_name());
            t.set_default_param(param_str);
            t.cursor = tool_t::general_tool[TOOL_PLANT_GROUNDOBJ]->cursor;
            welt->set_tool(&t, pl);
            return NULL;
        }
    }

    return gr->obj_count()>0 ? "Not allowed to copy object." : NULL;
}
Title: Re: pipette tool update request: pick way, pick tram-way
Post by: prissi on February 26, 2026, 12:42:51 PM
Thank you, incorporated in r11887