static item_location inv_internal( player &u, const inventory_selector_preset &preset,
                                   const std::string &title, int radius,
                                   const std::string &none_message )
{
    u.inv.restack( &u );
    u.inv.sort();

    inventory_pick_selector inv_s( u, preset );

    inv_s.set_title( title );
    inv_s.set_display_stats( false );

    inv_s.add_character_items( u );
    inv_s.add_nearby_items( radius );

    if( inv_s.empty() ) {
        const std::string msg = none_message.empty()
                                ? _( "You don't have the necessary item at hand." )
                                : none_message;
        popup( msg, PF_GET_KEY );
        return item_location();
    }

    return inv_s.execute();
}
void game::interactive_inv()
{
    static const std::set<int> allowed_selections = { { ' ', '.', 'q', '=', '\n', KEY_LEFT, KEY_ESCAPE } };

    u.inv.restack( &u );
    u.inv.sort();

    inventory_pick_selector inv_s( u );

    inv_s.add_character_items( u );
    inv_s.set_title( _( "Inventory" ) );

    int res;
    do {
        inv_s.set_hint( string_format(
                            _( "Item hotkeys assigned: <color_ltgray>%d</color>/<color_ltgray>%d</color>" ),
                            u.allocated_invlets().size(), inv_chars.size() - u.allocated_invlets().size() ) );
        const item_location &location = inv_s.execute();
        if( location == item_location::nowhere ) {
            break;
        }
        refresh_all();
        res = inventory_item_menu( u.get_item_position( location.get_item() ) );
        refresh_all();
    } while( allowed_selections.count( res ) != 0 );
}
int game::display_slice(indexed_invslice const &slice, const std::string &title, bool show_worn, const int position)
{
    inventory_selector inv_s(false, false, title);
    inv_s.make_item_list(slice);
    inv_s.prepare_paging();
    inv_s.select_item_by_position(position);

    while(true) {
        inv_s.display(show_worn);
        const std::string action = inv_s.ctxt.handle_input();
        const long ch = inv_s.ctxt.get_raw_input().get_first_input();
        const int item_pos = g->u.invlet_to_position( ch );
        if (item_pos != INT_MIN) {
            return item_pos;
        } else if (inv_s.handle_movement(action)) {
            continue;
        } else if (action == "CONFIRM" || action == "RIGHT") {
            return inv_s.get_selected_item_position();
        } else if (action == "QUIT") {
            return INT_MIN;
        } else {
            return INT_MIN;
        }
    }
}
std::list<std::pair<int, int>> game::multidrop()
{
    u.inv.restack( &u );
    u.inv.sort();

    inventory_selector inv_s( u, [ this ]( const item &it ) -> bool {
        return u.can_unwield( it, false );
    } );
    if( inv_s.empty() ) {
        popup( std::string( _( "You have nothing to drop." ) ), PF_GET_KEY );
        return std::list<std::pair<int, int> >();
    }
    return inv_s.execute_multidrop( _( "Multidrop:" ) );
}
int game::inv_for_filter( const std::string &title, item_filter filter, const std::string &none_message )
{
    u.inv.restack( &u );
    u.inv.sort();

    inventory_selector inv_s( u, filter );

    if( inv_s.empty() ) {
        const std::string msg = ( none_message.empty() ) ? _( "You don't have the necessary item." ) : none_message;
        popup( msg, PF_GET_KEY );
        return INT_MIN;
    }

    return inv_s.execute_pick( title );
}
void game::compare( const tripoint &offset )
{
    const tripoint examp = u.pos() + offset;

    std::vector<std::list<item>> grounditems;
    indexed_invslice grounditems_slice;

    if( !m.has_flag( "SEALED", u.pos() ) ) {
        auto here = m.i_at( examp );
        //Filter out items with the same name (keep only one of them)
        std::set<std::string> dups;
        for (size_t i = 0; i < here.size(); i++) {
            if (dups.count(here[i].tname()) == 0) {
                grounditems.push_back(std::list<item>(1, here[i]));

                //Only the first 10 items get a invlet
                if ( grounditems.size() <= 10 ) {
                    // invlet: '0' ... '9'
                    grounditems.back().front().invlet = '0' + grounditems.size() - 1;
                }

                dups.insert(here[i].tname());
            }
        }
        for (size_t a = 0; a < grounditems.size(); a++) {
            // avoid INT_MIN, as it can be confused with "no item at all"
            grounditems_slice.push_back(indexed_invslice::value_type(&grounditems[a], INT_MIN + a + 1));
        }
    }

    static const item_category category_on_ground( "GROUND", _( "GROUND" ), -1000 );

    u.inv.restack(&u);
    u.inv.sort();

    inventory_selector inv_s( u );

    inv_s.add_entries( grounditems_slice, &category_on_ground );
    if( inv_s.empty() ) {
        popup( std::string( _( "There are no items to compare." ) ), PF_GET_KEY );
        return;
    }
    inv_s.execute_compare( _( "Compare:" ) );
}
std::list<std::pair<int, int>> game::multidrop()
{
    u.inv.restack(&u);
    u.inv.sort();
    const indexed_invslice stacks = u.inv.slice_filter();
    inventory_selector inv_s(true, false, _("Multidrop:"));
    inv_s.make_item_list(stacks);
    inv_s.prepare_paging();
    int count = 0;
    while(true) {
        inv_s.display();
        const std::string action = inv_s.ctxt.handle_input();
        const long ch = inv_s.ctxt.get_raw_input().get_first_input();
        const int item_pos = g->u.invlet_to_position( ch );
        if (ch >= '0' && ch <= '9') {
            count = std::max( 0, count * 10 + ((char)ch - '0') );
        } else if (item_pos != INT_MIN) {
            inv_s.set_to_drop(item_pos, count);
            count = 0;
        } else if (inv_s.handle_movement(action)) {
            count = 0;
            continue;
        } else if (action == "CONFIRM") {
            break;
        } else if (action == "QUIT") {
            return std::list<std::pair<int, int> >();
        } else if (action == "RIGHT") {
            inv_s.set_selected_to_drop(count);
            count = 0;
        }
    }

    std::list<std::pair<int, int>> dropped_pos_and_qty;

    for( auto drop_pair : inv_s.dropping ) {
        int num_to_drop = drop_pair.second;
        if( num_to_drop == -1 ) {
            num_to_drop = inventory::num_items_at_position( drop_pair.first );
        }
        dropped_pos_and_qty.push_back( std::make_pair( drop_pair.first, num_to_drop ) );
    }

    return dropped_pos_and_qty;
}
void game::interactive_inv()
{
    static const std::set<int> allowed_selections = { { ' ', '.', 'q', '=', '\n', KEY_LEFT, KEY_ESCAPE } };

    u.inv.restack( &u );
    u.inv.sort();

    inventory_selector inv_s( u );

    int res;
    do {
        const int pos = inv_s.execute_pick( _( "Inventory:" ) );
        if( pos == INT_MIN ) {
            break;
        }
        refresh_all();
        res = inventory_item_menu( pos );
    } while( allowed_selections.count( res ) != 0 );
}
std::list<std::pair<int, int>> game::multidrop()
{
    u.inv.restack( &u );
    u.inv.sort();

    const inventory_filter_preset preset( [ this ]( const item_location & location ) {
        return u.can_unwield( *location, false );
    } );

    inventory_drop_selector inv_s( u, preset );

    inv_s.add_character_items( u );
    inv_s.set_title( _( "Multidrop" ) );
    inv_s.set_hint( _( "To drop x items, type a number before selecting." ) );

    if( inv_s.empty() ) {
        popup( std::string( _( "You have nothing to drop." ) ), PF_GET_KEY );
        return std::list<std::pair<int, int> >();
    }
    return inv_s.execute();
}
Example #10
0
void game_menus::inv::swap_letters( player &p )
{
    p.inv.restack( &p );
    p.inv.sort();

    inventory_pick_selector inv_s( p );

    inv_s.add_character_items( p );
    inv_s.set_title( _( "Swap Inventory Letters" ) );
    inv_s.set_display_stats( false );

    if( inv_s.empty() ) {
        popup( std::string( _( "Your inventory is empty." ) ), PF_GET_KEY );
        return;
    }

    while( true ) {
        const std::string invlets = colorize_symbols( inv_chars.get_allowed_chars(),
        [ &p ]( const std::string::value_type & elem ) {
            if( p.assigned_invlet.count( elem ) ) {
                return c_yellow;
            } else if( p.invlet_to_position( elem ) != INT_MIN ) {
                return c_white;
            } else {
                return c_dkgray;
            }
        } );

        inv_s.set_hint( invlets );

        auto loc = inv_s.execute();

        if( !loc ) {
            break;
        }

        reassign_letter( p, *loc );
        g->refresh_all();
    }
}
std::list<std::pair<int, int>> game_menus::inv::multidrop( player &p )
{
    p.inv.restack( &p );
    p.inv.sort();

    const inventory_filter_preset preset( [ &p ]( const item_location & location ) {
        return p.can_unwield( *location ).success();
    } );

    inventory_drop_selector inv_s( p, preset );

    inv_s.add_character_items( p );
    inv_s.set_title( _( "Multidrop" ) );
    inv_s.set_hint( _( "To drop x items, type a number before selecting." ) );

    if( inv_s.empty() ) {
        popup( std::string( _( "You have nothing to drop." ) ), PF_GET_KEY );
        return std::list<std::pair<int, int> >();
    }

    return inv_s.execute();
}
void game::compare( const tripoint &offset )
{
    u.inv.restack( &u );
    u.inv.sort();

    inventory_compare_selector inv_s( u );

    inv_s.add_character_items( u );
    inv_s.set_title( _( "Compare" ) );
    inv_s.set_hint( _( "Select two items to compare them." ) );

    if( offset != tripoint_min ) {
        inv_s.add_map_items( u.pos() + offset );
        inv_s.add_vehicle_items( u.pos() + offset );
    } else {
        inv_s.add_nearby_items();
    }

    if( inv_s.empty() ) {
        popup( std::string( _( "There are no items to compare." ) ), PF_GET_KEY );
        return;
    }

    do {
        const auto to_compare = inv_s.execute();

        if( to_compare.first == nullptr || to_compare.second == nullptr ) {
            break;
        }

        std::vector<iteminfo> vItemLastCh, vItemCh;
        std::string sItemLastCh, sItemCh, sItemLastTn, sItemTn;

        to_compare.first->info( true, vItemCh );
        sItemCh = to_compare.first->tname();
        sItemTn = to_compare.first->type_name();

        to_compare.second->info( true, vItemLastCh );
        sItemLastCh = to_compare.second->tname();
        sItemLastTn = to_compare.second->type_name();

        int iScrollPos = 0;
        int iScrollPosLast = 0;
        int ch = ( int ) ' ';

        do {
            draw_item_info( 0, ( TERMX - VIEW_OFFSET_X * 2 ) / 2, 0, TERMY - VIEW_OFFSET_Y * 2,
                            sItemLastCh, sItemLastTn, vItemLastCh, vItemCh, iScrollPosLast, true ); //without getch(
            ch = draw_item_info( ( TERMX - VIEW_OFFSET_X * 2 ) / 2, ( TERMX - VIEW_OFFSET_X * 2 ) / 2,
                                 0, TERMY - VIEW_OFFSET_Y * 2, sItemCh, sItemTn, vItemCh, vItemLastCh, iScrollPos );

            if( ch == KEY_PPAGE ) {
                iScrollPos--;
                iScrollPosLast--;
            } else if( ch == KEY_NPAGE ) {
                iScrollPos++;
                iScrollPosLast++;
            }

            refresh_all();
        } while( ch == KEY_PPAGE || ch == KEY_NPAGE );
    } while( true );
}
Example #13
0
void game::compare(int iCompareX, int iCompareY)
{
    int examx, examy;

    if (iCompareX != -999 && iCompareY != -999) {
        examx = u.posx + iCompareX;
        examy = u.posy + iCompareY;
    } else if (!choose_adjacent(_("Compare where?"), examx, examy)) {
        return;
    }

    std::vector <item> &here = m.i_at(examx, examy);
    typedef std::vector< std::list<item> > pseudo_inventory;
    pseudo_inventory grounditems;
    indexed_invslice grounditems_slice;
    //Filter out items with the same name (keep only one of them)
    //Only the first 10 Items due to numbering 0-9
    std::set<std::string> dups;
    for (size_t i = 0; i < here.size() && grounditems.size() < 10; i++) {
        if (dups.count(here[i].tname()) == 0) {
            grounditems.push_back(std::list<item>(1, here[i]));
            // invlet: '0' ... '9'
            grounditems.back().front().invlet = '0' + grounditems.size() - 1;
            dups.insert(here[i].tname());
        }
    }
    for (size_t a = 0; a < grounditems.size(); a++) {
        // avoid INT_MIN, as it can be confused with "no item at all"
        grounditems_slice.push_back(indexed_invslice::value_type(&grounditems[a], INT_MIN + a + 1));
    }
    static const item_category category_on_ground(
        "GROUND:",
        _("GROUND:"),
        -1000
    );

    u.inv.restack(&u);
    u.inv.sort();
    const indexed_invslice stacks = u.inv.slice_filter();

    inventory_selector inv_s(false, true, _("Compare:"));
    inv_s.make_item_list(grounditems_slice, &category_on_ground);
    inv_s.make_item_list(stacks);
    inv_s.prepare_paging();

    inventory_selector::drop_map prev_droppings;
    while(true) {
        inv_s.display();
        const std::string action = inv_s.ctxt.handle_input();
        const long ch = inv_s.ctxt.get_raw_input().get_first_input();
        const int item_pos = g->u.invlet_to_position(static_cast<char>(ch));
        if (item_pos != INT_MIN) {
            inv_s.set_to_drop(item_pos, 0);
        } else if (ch >= '0' && ch <= '9' && (size_t) (ch - '0') < grounditems_slice.size()) {
            const int ip = ch - '0';
            inv_s.set_drop_count(INT_MIN + 1 + ip, 0, grounditems_slice[ip].first->front());
        } else if (inv_s.handle_movement(action)) {
            // continue with comparison below
        } else if (action == "QUIT") {
            break;
        } else if (action == "RIGHT") {
            inv_s.set_selected_to_drop(0);
        }
        if (inv_s.second_item != NULL) {
            std::vector<iteminfo> vItemLastCh, vItemCh;
            std::string sItemLastCh, sItemCh;
            inv_s.first_item->info(true, &vItemCh);
            sItemCh = inv_s.first_item->tname();
            inv_s.second_item->info(true, &vItemLastCh);
            sItemLastCh = inv_s.second_item->tname();
            draw_item_info(0, (TERMX - VIEW_OFFSET_X * 2) / 2, 0, TERMY - VIEW_OFFSET_Y * 2,
                           sItemLastCh, vItemLastCh, vItemCh, -1, true); //without getch()
            draw_item_info((TERMX - VIEW_OFFSET_X * 2) / 2, (TERMX - VIEW_OFFSET_X * 2) / 2,
                           0, TERMY - VIEW_OFFSET_Y * 2, sItemCh, vItemCh, vItemLastCh);
            inv_s.dropping = prev_droppings;
            inv_s.second_item = NULL;
        } else {
            prev_droppings = inv_s.dropping;
        }
    }
}
std::vector<item> game::multidrop(std::vector<item> &dropped_worn, int &freed_volume_capacity)
{
    freed_volume_capacity = 0;

    u.inv.restack(&u);
    u.inv.sort();
    const indexed_invslice stacks = u.inv.slice_filter();
    inventory_selector inv_s(true, false, _("Multidrop:"));
    inv_s.make_item_list(stacks);
    inv_s.prepare_paging();
    int count = 0;
    while(true) {
        inv_s.display();
        const std::string action = inv_s.ctxt.handle_input();
        const long ch = inv_s.ctxt.get_raw_input().get_first_input();
        const int item_pos = g->u.invlet_to_position(static_cast<char>(ch));
        if (ch >= '0' && ch <= '9') {
            count = count * 10 + ((char)ch - '0');
        } else if (item_pos != INT_MIN) {
            inv_s.set_to_drop(item_pos, count);
            count = 0;
        } else if (inv_s.handle_movement(action)) {
            count = 0;
            continue;
        } else if (action == "CONFIRM") {
            break;
        } else if (action == "QUIT") {
            return std::vector<item>();
        } else if (action == "RIGHT") {
            inv_s.set_selected_to_drop(count);
            count = 0;
        }
    }

    std::vector<item> ret;

    ret = inv_s.remove_dropping_items(g->u);
    const inventory_selector::drop_map &dropping = inv_s.dropping;
    const inventory_selector::drop_map::const_iterator dit = dropping.find(-1);
    if (dit != dropping.end()) {
        if (dit->second == -1) {
            ret.push_back(u.remove_weapon());
        } else {
            ret.push_back(u.weapon);
            u.weapon.charges -= dit->second;
            ret.back().charges = dit->second;
        }
    }
    // We iterate backwards because deletion will invalidate later indices.
    for( int k = u.worn.size() - 1; k >= 0; k-- ) {
        const int wornpos = player::worn_position_to_index( k );
        if( dropping.count( wornpos ) == 0 ) {
            continue;
        }
        const it_armor *ita = dynamic_cast<const it_armor *>( u.worn[k].type );
        const char invlet = u.worn[k].invlet; // TODO: might be 0
        if( !u.takeoff( wornpos, true ) ) {
            continue;
        }
        u.moves -= 250; // same as in game::takeoff
        if( ita != NULL ) {
            freed_volume_capacity += ita->storage;
        }
        // Item could have been dropped after taking it off
        if( !u.inv.item_by_letter( invlet ).is_null() ) {
            dropped_worn.push_back( u.i_rem( invlet ) );
        }
    }

    return ret;
}
item_location game::inv_map_splice(
    item_filter inv_filter, item_filter ground_filter, item_filter vehicle_filter,
    const std::string &title, int radius, const std::string &none_message )
{
    u.inv.restack( &u );
    u.inv.sort();

    inventory_selector inv_s( u, inv_filter );

    std::list<item_category> categories;
    int rank = -1000;

    // items are stacked per tile considering vehicle and map tiles separately
    // in the below loops identical items on the same tile are grouped into lists
    // each element of stacks represents one tile and is a vector of such lists
    std::vector<std::vector<std::list<item>>> stacks;

    // an indexed_invslice is created for each map or vehicle tile
    // each list of items created above for the tile will be added to it
    std::vector<indexed_invslice> slices;

    // of one of the above lists so use this as the key when storing the item location
    std::unordered_map<item *, item_location> opts;

    // the closest 10 items also have their location added to the invlets vector
    const char min_invlet = '0';
    const char max_invlet = '9';
    char cur_invlet = min_invlet;

    for( const auto &pos : closest_tripoints_first( radius, g->u.pos() ) ) {
        // second get all matching items on the map within radius
        if( m.accessible_items( g->u.pos(), pos, radius ) ) {
            auto items = m.i_at( pos );

            // create a new slice and stack for the current map tile
            stacks.emplace_back();
            slices.emplace_back();

            // reserve sufficient capacity to ensure reallocation is not required
            auto &current_stack = stacks.back();
            current_stack.reserve( items.size() );

            for( item &it : items ) {
                if( ground_filter( it ) ) {
                    auto match = std::find_if( current_stack.begin(),
                    current_stack.end(), [&]( const std::list<item> &e ) {
                        return it.stacks_with( e.back() );
                    } );
                    if( match != current_stack.end() ) {
                        match->push_back( it );
                    } else {
                        // item doesn't stack with any previous so start new list and append to current indexed_invslice
                        current_stack.emplace_back( 1, it );
                        slices.back().emplace_back( &current_stack.back(), INT_MIN );
                        opts.emplace( &current_stack.back().front(), item_location( pos, &it ) );

                        current_stack.back().front().invlet = ( cur_invlet <= max_invlet ) ? cur_invlet++ : 0;
                    }
                }
            }
            std::string name = trim( std::string( _( "GROUND" ) ) + " " + direction_suffix( g->u.pos(), pos ) );
            categories.emplace_back( name, name, rank++ );
            inv_s.add_entries( slices.back(), &categories.back() );
        }

        // finally get all matching items in vehicle cargo spaces
        int part = -1;
        vehicle *veh = m.veh_at( pos, part );
        if( veh && part >= 0 ) {
            part = veh->part_with_feature( part, "CARGO" );
            if( part != -1 ) {
                auto items = veh->get_items( part );

                // create a new slice and stack for the current vehicle part
                stacks.emplace_back();
                slices.emplace_back();

                // reserve sufficient capacity to ensure reallocation is not required
                auto &current_stack = stacks.back();
                current_stack.reserve( items.size() );

                for( item &it : items ) {
                    if( vehicle_filter( it ) ) {
                        auto match = std::find_if( current_stack.begin(),
                        current_stack.end(), [&]( const std::list<item> &e ) {
                            return it.stacks_with( e.back() );
                        } );
                        if( match != current_stack.end() ) {
                            match->push_back( it );
                        } else {
                            // item doesn't stack with any previous so start new list and append to current indexed_invslice
                            current_stack.emplace_back( 1, it );
                            slices.back().emplace_back( &current_stack.back(), INT_MIN );
                            opts.emplace( &current_stack.back().front(), item_location( vehicle_cursor( *veh, part ), &it ) );

                            current_stack.back().front().invlet = ( cur_invlet <= max_invlet ) ? cur_invlet++ : 0;
                        }
                    }
                }
                std::string name = trim( std::string( _( "VEHICLE" ) )  + " " + direction_suffix( g->u.pos(), pos ) );
                categories.emplace_back( name, name, rank-- );
                inv_s.add_entries( slices.back(), &categories.back() );
            }
        }
    }

    if( inv_s.empty() ) {
        const std::string msg = ( none_message.empty() ) ? _( "You don't have the necessary item at hand." ) : none_message;
        popup( msg, PF_GET_KEY );
        return item_location();
    }
    return inv_s.execute_pick_map( title, opts );
}
Example #16
0
void game::compare( const tripoint &offset )
{
    const tripoint examp = u.pos3() + offset;

    std::vector<std::list<item>> grounditems;
    indexed_invslice grounditems_slice;
    if( !m.has_flag( "SEALED", g->u.pos() ) ) {
        auto here = m.i_at( examp );
        //Filter out items with the same name (keep only one of them)
        std::set<std::string> dups;
        for (size_t i = 0; i < here.size(); i++) {
            if (dups.count(here[i].tname()) == 0) {
                grounditems.push_back(std::list<item>(1, here[i]));

                //Only the first 10 items get a invlet
                if ( grounditems.size() <= 10 ) {
                    // invlet: '0' ... '9'
                    grounditems.back().front().invlet = '0' + grounditems.size() - 1;
                }

                dups.insert(here[i].tname());
            }
        }
        for (size_t a = 0; a < grounditems.size(); a++) {
            // avoid INT_MIN, as it can be confused with "no item at all"
            grounditems_slice.push_back(indexed_invslice::value_type(&grounditems[a], INT_MIN + a + 1));
        }
    }
    static const item_category category_on_ground(
        "GROUND:",
        _("GROUND:"),
        -1000
    );

    u.inv.restack(&u);
    u.inv.sort();
    const indexed_invslice stacks = u.inv.slice_filter();

    inventory_selector inv_s(false, true, _("Compare:"));
    inv_s.make_item_list(grounditems_slice, &category_on_ground);
    inv_s.make_item_list(stacks);
    inv_s.prepare_paging();

    inventory_selector::drop_map prev_droppings;
    while(true) {
        inv_s.display();
        const std::string action = inv_s.ctxt.handle_input();
        const long ch = inv_s.ctxt.get_raw_input().get_first_input();
        const int item_pos = g->u.invlet_to_position( ch );
        if (item_pos != INT_MIN) {
            inv_s.set_to_drop(item_pos, 0);
        } else if (ch >= '0' && ch <= '9' && (size_t) (ch - '0') < grounditems_slice.size()) {
            const int ip = ch - '0';
            inv_s.set_drop_count(INT_MIN + 1 + ip, 0, grounditems_slice[ip].first->front());
        } else if (inv_s.handle_movement(action)) {
            // continue with comparison below
        } else if (action == "QUIT") {
            break;
        } else if (action == "RIGHT") {
            inv_s.set_selected_to_drop(0);
        }
        if (inv_s.second_item != NULL) {
            std::vector<iteminfo> vItemLastCh, vItemCh;
            std::string sItemLastCh, sItemCh, sItemTn;
            inv_s.first_item->info(true, vItemCh);
            sItemCh = inv_s.first_item->tname();
            sItemTn = inv_s.first_item->type_name();
            inv_s.second_item->info(true, vItemLastCh);
            sItemLastCh = inv_s.second_item->tname();

            int iScrollPos = 0;
            int iScrollPosLast = 0;
            int ch = (int)' ';
            do {
                draw_item_info(0, (TERMX - VIEW_OFFSET_X * 2) / 2, 0, TERMY - VIEW_OFFSET_Y * 2,
                               sItemLastCh, sItemTn, vItemLastCh, vItemCh, iScrollPosLast, true); //without getch()
                ch = draw_item_info((TERMX - VIEW_OFFSET_X * 2) / 2, (TERMX - VIEW_OFFSET_X * 2) / 2,
                                    0, TERMY - VIEW_OFFSET_Y * 2, sItemCh, sItemTn, vItemCh, vItemLastCh, iScrollPos);

                if ( ch == KEY_PPAGE ) {
                    iScrollPos--;
                    iScrollPosLast--;
                } else if ( ch == KEY_NPAGE ) {
                    iScrollPos++;
                    iScrollPosLast++;
                }
            } while (ch == KEY_PPAGE || ch == KEY_NPAGE);

            inv_s.dropping = prev_droppings;
            inv_s.second_item = NULL;
        } else {
            prev_droppings = inv_s.dropping;
        }
    }
}
Example #17
0
item *game::inv_map_for_liquid(const item &liquid, const std::string title)
{
    std::vector <item> &here = m.i_at(g->u.posx, g->u.posy);
    typedef std::vector< std::list<item> > pseudo_inventory;
    pseudo_inventory grounditems;
    indexed_invslice grounditems_slice;
    std::vector<item *> ground_containers;

    LIQUID_FILL_ERROR error;

    std::set<std::string> dups;
    for( auto item_iter = here.begin(); item_iter != here.end(); ++item_iter ) {
        if( item_iter->get_remaining_capacity_for_liquid(liquid, error) > 0 ) {
            if( dups.count( item_iter->tname()) == 0 ) {
                grounditems.push_back( std::list<item>(1, *item_iter) );

                if( grounditems.size() <= 10 ) {
                    grounditems.back().front().invlet = '0' + grounditems.size() - 1;
                } else {
                    grounditems.back().front().invlet = ' ';
                }
                dups.insert( item_iter->tname() );

                ground_containers.push_back( &*item_iter );
            }
        }
    }

    for (size_t a = 0; a < grounditems.size(); a++) {
        // avoid INT_MIN, as it can be confused with "no item at all"
        grounditems_slice.push_back(indexed_invslice::value_type(&grounditems[a], INT_MIN + a + 1));
    }
    static const item_category category_on_ground(
        "GROUND:",
        _("GROUND:"),
        -1000
    );

    u.inv.restack(&u);
    u.inv.sort();
    const indexed_invslice stacks = u.inv.slice_filter_by_capacity_for_liquid(liquid);

    inventory_selector inv_s(false, true, title);
    inv_s.make_item_list(grounditems_slice, &category_on_ground);
    inv_s.make_item_list(stacks);
    inv_s.prepare_paging();

    inventory_selector::drop_map prev_droppings;
    while (true) {
        inv_s.display();
        const std::string action = inv_s.ctxt.handle_input();
        const long ch = inv_s.ctxt.get_raw_input().get_first_input();
        const int item_pos = g->u.invlet_to_position(static_cast<char>(ch));

        if (item_pos != INT_MIN) {
            inv_s.set_to_drop(item_pos, 0);
            return inv_s.first_item;
        } else if (ch >= '0' && ch <= '9' && (size_t)(ch - '0') < grounditems_slice.size()) {
            const int ip = ch - '0';
            return ground_containers[ip];
        } else if (inv_s.handle_movement(action)) {
            // continue with comparison below
        } else if (action == "QUIT") {
            return NULL;
        } else if (action == "RIGHT" || action == "CONFIRM") {

            inv_s.set_selected_to_drop(0);

            for( size_t i = 0; i < grounditems_slice.size(); i++) {
                if( &grounditems_slice[i].first->front() == inv_s.first_item ) {
                    return ground_containers[i];
                }
            }

            return inv_s.first_item;
        }
    }
}
Example #18
0
item_location game::inv_map_splice(
    item_filter inv_filter, item_filter ground_filter, item_filter vehicle_filter,
    const std::string &title, int radius )
{
    inventory_selector inv_s( false, false, title );

    // first get matching items from the inventory
    u.inv.restack( &u );
    u.inv.sort();
    inv_s.make_item_list( u.inv.slice_filter_by( inv_filter ) );

    // items are stacked per tile considering vehicle and map tiles separately
    static const item_category ground_cat( "GROUND:",  _( "GROUND:" ),  -1000 );
    static const item_category nearby_cat( "NEARBY:",  _( "NEARBY:" ),  -2000 );
    static const item_category vehicle_cat( "VEHICLE:", _( "VEHICLE:" ), -3000 );

    // in the below loops identical items on the same tile are grouped into lists
    // each element of stacks represents one tile and is a vector of such lists
    std::vector<std::vector<std::list<item>>> stacks;

    // an indexed_invslice is created for each map or vehicle tile
    // each list of items created above for the tile will be added to it
    std::vector<indexed_invslice> slices;

    // inv_s.first_item will later contain the chosen item as a pointer to first item
    // of one of the above lists so use this as the key when storing the item location
    std::unordered_map<item *, item_location> opts;

    // the closest 10 items also have their location added to the invlets vector
    const char min_invlet = '0';
    const char max_invlet = '9';
    char cur_invlet = min_invlet;
    std::vector<item_location> invlets;

    for( const auto &pos : closest_tripoints_first( radius, g->u.pos() ) ) {
        // second get all matching items on the map within radius
        if( m.accessible_items( g->u.pos(), pos, radius ) ) {
            auto items = m.i_at( pos );

            // create a new slice and stack for the current map tile
            stacks.emplace_back();
            slices.emplace_back();

            // reserve sufficient capacity to ensure reallocation is not required
            auto &current_stack = stacks.back();
            current_stack.reserve( items.size() );

            for( item &it : items ) {
                if( ground_filter( it ) ) {
                    auto match = std::find_if( current_stack.begin(),
                    current_stack.end(), [&]( const std::list<item> &e ) {
                        return it.stacks_with( e.back() );
                    } );
                    if( match != current_stack.end() ) {
                        match->push_back( it );
                    } else {
                        // item doesn't stack with any previous so start new list and append to current indexed_invslice
                        current_stack.emplace_back( 1, it );
                        slices.back().emplace_back( &current_stack.back(), INT_MIN );
                        opts.emplace( &current_stack.back().front(), item_location::on_map( pos, &it ) );

                        if( cur_invlet <= max_invlet ) {
                            current_stack.back().front().invlet = cur_invlet++;
                            invlets.emplace_back( item_location::on_map( pos, &it ) );
                        } else {
                            current_stack.back().front().invlet = 0;
                        }
                    }
                }
            }
            inv_s.make_item_list( slices.back(), pos == g->u.pos() ? &ground_cat : &nearby_cat );
        }

        // finally get all matching items in vehicle cargo spaces
        int part = -1;
        vehicle *veh = m.veh_at( pos, part );
        if( veh && part >= 0 ) {
            part = veh->part_with_feature( part, "CARGO" );
            if( part != -1 ) {
                auto items = veh->get_items( part );

                // create a new slice and stack for the current vehicle part
                stacks.emplace_back();
                slices.emplace_back();

                // reserve sufficient capacity to ensure reallocation is not required
                auto &current_stack = stacks.back();
                current_stack.reserve( items.size() );

                for( item &it : items ) {
                    if( vehicle_filter( it ) ) {
                        auto match = std::find_if( current_stack.begin(),
                        current_stack.end(), [&]( const std::list<item> &e ) {
                            return it.stacks_with( e.back() );
                        } );
                        if( match != current_stack.end() ) {
                            match->push_back( it );
                        } else {
                            // item doesn't stack with any previous so start new list and append to current indexed_invslice
                            current_stack.emplace_back( 1, it );
                            slices.back().emplace_back( &current_stack.back(), INT_MIN );
                            opts.emplace( &current_stack.back().front(), item_location::on_vehicle( *veh,
                                          veh->parts[part].mount, &it ) );

                            if( cur_invlet <= max_invlet ) {
                                current_stack.back().front().invlet = cur_invlet++;
                                invlets.emplace_back( item_location::on_vehicle( *veh, veh->parts[part].mount, &it ) );
                            } else {
                                current_stack.back().front().invlet = 0;
                            }
                        }
                    }
                }
                inv_s.make_item_list( slices.back(), &vehicle_cat );
            }
        }
    }

    inv_s.prepare_paging();

    while( true ) {
        inv_s.display();
        const std::string action = inv_s.ctxt.handle_input();
        const long ch = inv_s.ctxt.get_raw_input().get_first_input();
        const int item_pos = g->u.invlet_to_position( ch );

        if( item_pos != INT_MIN ) {
            // Indexed item in inventory
            inv_s.set_to_drop( item_pos, 0 );
            return item_location::on_character( u, inv_s.first_item );

        } else if( ch >= min_invlet && ch <= max_invlet ) {
            // Indexed item on ground or in vehicle
            if( (long)invlets.size() > ch - min_invlet ) {
                return std::move( invlets[ch - min_invlet] );
            }

        } else if( inv_s.handle_movement( action ) ) {
            // continue with comparison below

        } else if( action == "QUIT" ) {
            return item_location::nowhere();

        } else if( action == "RIGHT" || action == "CONFIRM" ) {
            inv_s.set_selected_to_drop( 0 );

            // Item in inventory
            if( inv_s.get_selected_item_position() != INT_MIN ) {
                return item_location::on_character( u, inv_s.first_item );
            }
            // Item on ground or in vehicle
            auto it = opts.find( inv_s.first_item );
            if( it != opts.end() ) {
                return std::move( it->second );
            }

            return item_location::nowhere();
        }
    }
}
Example #19
0
item_location game::inv_map_splice(
    item_filter inv_filter, item_filter ground_filter, item_filter vehicle_filter, const std::string &title )
{
    char cur_invlet = '0';

    pseudo_inventory ground_items;
    pseudo_inventory vehicle_items;

    std::vector<item *> ground_selectables;
    std::vector<item *> vehicle_selectables;

    indexed_invslice ground_items_slice;
    indexed_invslice veh_items_slice;

    pseudo_inv_to_slice( m.i_at( g->u.pos() ), ground_filter,
                         ground_items, ground_items_slice,
                         ground_selectables, cur_invlet );


    int part = -1;
    vehicle *veh = m.veh_at( g->u.pos(), part );
    point veh_pt( INT_MIN, INT_MIN );
    if( veh != nullptr && part >= 0 ) {
        part = veh->part_with_feature( part, "CARGO" );
        if( part != -1 ) {
            veh_pt = veh->parts[part].mount;
            pseudo_inv_to_slice( veh->get_items( part ), vehicle_filter,
                                 vehicle_items, veh_items_slice,
                                 vehicle_selectables, cur_invlet );
        }
    }

    static const item_category category_on_ground(
        "GROUND:",
        _("GROUND:"),
        -1000
    );

    static const item_category category_on_veh(
        "VEHICLE:",
        _("VEHICLE:"),
        -2000
    );

    u.inv.restack(&u);
    u.inv.sort();
    const indexed_invslice stacks = u.inv.slice_filter_by( inv_filter );

    inventory_selector inv_s(false, false, title);
    inv_s.make_item_list(stacks);
    inv_s.make_item_list(ground_items_slice, &category_on_ground);
    inv_s.make_item_list(veh_items_slice, &category_on_veh);
    inv_s.prepare_paging();

    inventory_selector::drop_map prev_droppings;
    while( true ) {
        inv_s.display();
        const std::string action = inv_s.ctxt.handle_input();
        const long ch = inv_s.ctxt.get_raw_input().get_first_input();
        const int item_pos = g->u.invlet_to_position( static_cast<char>( ch ) );

        if( item_pos != INT_MIN ) {
            inv_s.set_to_drop(item_pos, 0);
            // In the inventory
            return item_location::on_character( u, inv_s.first_item );
        } else if( ch >= first_invlet && ch <= last_invlet ) {
            // Indexed results on the ground or vehicle
            const size_t index = (size_t)(ch - first_invlet);
            if( index < ground_items_slice.size() ) {
                // Ground item
                return item_location::on_map( u.pos(), ground_selectables[index] );
            } else if( index < ground_items_slice.size() + veh_items_slice.size() ) {
                // Vehicle item
                return item_location::on_vehicle( *veh, veh_pt, vehicle_selectables[index] );
            }
        } else if( inv_s.handle_movement( action ) ) {
            // continue with comparison below
        } else if( action == "QUIT" ) {
            return item_location::nowhere();
        } else if( action == "RIGHT" || action == "CONFIRM" ) {
            inv_s.set_selected_to_drop(0);

            for( size_t i = 0; i < ground_items_slice.size(); i++) {
                if( &ground_items_slice[i].first->front() == inv_s.first_item ) {
                    // Ground item, may be unindexed
                    return item_location::on_map( u.pos(), ground_selectables[i] );
                }
            }

            for( size_t i = 0; i < veh_items_slice.size(); i++) {
                if( &veh_items_slice[i].first->front() == inv_s.first_item ) {
                    // Vehicle item
                    return item_location::on_vehicle( *veh, veh_pt, vehicle_selectables[i] );
                }
            }

            // Inventory item or possibly nothing
            int inv_pos = inv_s.get_selected_item_position();
            if( inv_pos == INT_MIN ) {
                return item_location::nowhere();
            } else {
                return item_location::on_character( u, inv_s.first_item );
            }
        }
    }
}