Example #1
0
	bool NPC::action(Environment& env){

		float r = ((float) rand() / (RAND_MAX));
		if (r < go_prob){
			//GO
			std::vector<std::string> directions = env.directions();
			if (directions.size() > 0){
				int random_index = rand() % directions.size();
				std::string direction = directions[random_index];
				go(env, direction);
			}

		}

		r = ((float) rand() / (RAND_MAX));
		if (r < fight_prob){
			//FIGHT
			Character* player = env.get_player();
			if (player != NULL){
				fight(*player, env);
			}
		}

		r = ((float) rand() / (RAND_MAX));
		if (r < pickup_prob){
			//PICK UP
			if (env.get_object_names().size() > 0){
				std::vector<std::string> object_names = env.get_object_names();
				int random_index = rand() % object_names.size();
				std::string name = object_names[random_index];
				Object* object = env.get_object(name);
				env.pick_up(*object);
				pick_up(*object);
			}
		}

		r = ((float) rand() / (RAND_MAX));
		if (r < drop_prob){
			//DROP
			std::vector<Object *> inventory = (*container).get_objects();
			if (inventory.size() > 0){
				int random_index = rand() % inventory.size();
				Object& object = *inventory[random_index];
				env.drop(object);
				drop(object);
			}
		}
		return true;
	}
Example #2
0
// Pick up items at (pos).
void Pickup::pick_up( const tripoint &pos, int min )
{
    int veh_root_part = 0;
    int cargo_part = -1;

    vehicle *veh = g->m.veh_at( pos, veh_root_part );
    bool from_vehicle = false;

    if( min != -1 ) {
        switch( interact_with_vehicle( veh, pos, veh_root_part ) ) {
            case DONE:
                return;
            case ITEMS_FROM_CARGO:
                cargo_part = veh->part_with_feature( veh_root_part, "CARGO", false );
                from_vehicle = cargo_part >= 0;
                break;
            case ITEMS_FROM_GROUND:
                // Nothing to change, default is to pick from ground anyway.
                if( g->m.has_flag( "SEALED", pos ) ) {
                    return;
                }

                break;
        }
    }

    if( !from_vehicle ) {
        bool isEmpty = ( g->m.i_at( pos ).empty() );

        // Hide the pickup window if this is a toilet and there's nothing here
        // but water.
        if( ( !isEmpty ) && g->m.furn( pos ) == f_toilet ) {
            isEmpty = true;
            for( auto maybe_water : g->m.i_at( pos ) ) {
                if( maybe_water.typeId() != "water" ) {
                    isEmpty = false;
                    break;
                }
            }
        }

        if( isEmpty && ( min != -1 || !OPTIONS["AUTO_PICKUP_ADJACENT"] ) ) {
            return;
        }
    }

    // which items are we grabbing?
    std::vector<item> here;
    if( from_vehicle ) {
        auto vehitems = veh->get_items( cargo_part );
        here.resize( vehitems.size() );
        std::copy( vehitems.rbegin(), vehitems.rend(), here.begin() );
    } else {
        auto mapitems = g->m.i_at( pos );
        here.resize( mapitems.size() );
        std::copy( mapitems.rbegin(), mapitems.rend(), here.begin() );
    }

    if( min == -1 ) {
        if( g->check_zone( "NO_AUTO_PICKUP", pos ) ) {
            here.clear();
        }

        // Recursively pick up adjacent items if that option is on.
        if( OPTIONS["AUTO_PICKUP_ADJACENT"] && g->u.pos() == pos ) {
            //Autopickup adjacent
            direction adjacentDir[8] = {NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, NORTHWEST};
            for( auto &elem : adjacentDir ) {

                tripoint apos = tripoint( direction_XY( elem ), 0 );
                apos += pos;

                if( g->m.has_flag( "SEALED", apos ) ) {
                    continue;
                }
                if( g->check_zone( "NO_AUTO_PICKUP", apos ) ) {
                    continue;
                }
                pick_up( apos, min );
            }
        }
    }

    // Not many items, just grab them
    if( ( int )here.size() <= min && min != -1 ) {
        g->u.assign_activity( ACT_PICKUP, 0 );
        g->u.activity.placement = pos - g->u.pos();
        g->u.activity.values.push_back( from_vehicle );
        // Only one item means index is 0.
        g->u.activity.values.push_back( 0 );
        // auto-pickup means pick up all.
        g->u.activity.values.push_back( 0 );
        return;
    }

    if( min != -1 ) { // don't bother if we're just autopickup-ing
        g->temp_exit_fullscreen();
    }
    bool sideStyle = use_narrow_sidebar();

    // Otherwise, we have Autopickup, 2 or more items and should list them, etc.
    int maxmaxitems = sideStyle ? TERMY : getmaxy( g->w_messages ) - 3;

    int itemsH = std::min( 25, TERMY / 2 );
    int pickupBorderRows = 3;

    // The pickup list may consume the entire terminal, minus space needed for its
    // header/footer and the item info window.
    int minleftover = itemsH + pickupBorderRows;
    if( maxmaxitems > TERMY - minleftover ) {
        maxmaxitems = TERMY - minleftover;
    }

    const int minmaxitems = sideStyle ? 6 : 9;

    std::vector<pickup_count> getitem( here.size() );

    int maxitems = here.size();
    maxitems = ( maxitems < minmaxitems ? minmaxitems : ( maxitems > maxmaxitems ? maxmaxitems :
                 maxitems ) );

    int itemcount = 0;

    if( min == -1 ) { //Auto Pickup, select matching items
        if( !select_autopickup_items( here, getitem ) ) {
            // If we didn't find anything, bail out now.
            return;
        }
    } else {
        int pickupH = maxitems + pickupBorderRows;
        int pickupW = getmaxx( g->w_messages );
        int pickupY = VIEW_OFFSET_Y;
        int pickupX = getbegx( g->w_messages );

        int itemsW = pickupW;
        int itemsY = sideStyle ? pickupY + pickupH : TERMY - itemsH;
        int itemsX = pickupX;

        WINDOW *w_pickup    = newwin( pickupH, pickupW, pickupY, pickupX );
        WINDOW *w_item_info = newwin( itemsH,  itemsW,  itemsY,  itemsX );
        WINDOW_PTR w_pickupptr( w_pickup );
        WINDOW_PTR w_item_infoptr( w_item_info );

        std::string action;
        long raw_input_char = ' ';
        input_context ctxt( "PICKUP" );
        ctxt.register_action( "UP" );
        ctxt.register_action( "DOWN" );
        ctxt.register_action( "RIGHT" );
        ctxt.register_action( "LEFT" );
        ctxt.register_action( "NEXT_TAB", _( "Next page" ) );
        ctxt.register_action( "PREV_TAB", _( "Previous page" ) );
        ctxt.register_action( "SCROLL_UP" );
        ctxt.register_action( "SCROLL_DOWN" );
        ctxt.register_action( "CONFIRM" );
        ctxt.register_action( "SELECT_ALL" );
        ctxt.register_action( "QUIT", _( "Cancel" ) );
        ctxt.register_action( "ANY_INPUT" );
        ctxt.register_action( "HELP_KEYBINDINGS" );

        int start = 0, cur_it;
        player pl_copy = g->u;
        pl_copy.set_fake( true );
        bool update = true;
        mvwprintw( w_pickup, 0, 0, _( "PICK UP" ) );
        int selected = 0;
        int iScrollPos = 0;

        if( g->was_fullscreen ) {
            g->draw_ter();
        }
        // Now print the two lists; those on the ground and about to be added to inv
        // Continue until we hit return or space
        do {
            const std::string pickup_chars =
                ctxt.get_available_single_char_hotkeys( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:;" );
            int idx = -1;
            for( int i = 1; i < pickupH; i++ ) {
                mvwprintw( w_pickup, i, 0,
                           "                                                " );
            }
            if( action == "ANY_INPUT" &&
                raw_input_char >= '0' && raw_input_char <= '9' ) {
                int raw_input_char_value = ( char )raw_input_char - '0';
                itemcount *= 10;
                itemcount += raw_input_char_value;
                if( itemcount < 0 ) {
                    itemcount = 0;
                }
            } else if( action == "SCROLL_UP" ) {
                iScrollPos--;
            } else if( action == "SCROLL_DOWN" ) {
                iScrollPos++;
            } else if( action == "PREV_TAB" ) {
                if( start > 0 ) {
                    start -= maxitems;
                } else {
                    start = ( int )( ( here.size() - 1 ) / maxitems ) * maxitems;
                }
                selected = start;
                mvwprintw( w_pickup, maxitems + 2, 0, "         " );
            } else if( action == "NEXT_TAB" ) {
                if( start + maxitems < ( int )here.size() ) {
                    start += maxitems;
                } else {
                    start = 0;
                }
                iScrollPos = 0;
                selected = start;
                mvwprintw( w_pickup, maxitems + 2, pickupH, "            " );
            } else if( action == "UP" ) {
                selected--;
                iScrollPos = 0;
                if( selected < 0 ) {
                    selected = here.size() - 1;
                    start = ( int )( here.size() / maxitems ) * maxitems;
                    if( start >= ( int )here.size() ) {
                        start -= maxitems;
                    }
                } else if( selected < start ) {
                    start -= maxitems;
                }
            } else if( action == "DOWN" ) {
                selected++;
                iScrollPos = 0;
                if( selected >= ( int )here.size() ) {
                    selected = 0;
                    start = 0;
                } else if( selected >= start + maxitems ) {
                    start += maxitems;
                }
            } else if( selected >= 0 && (
                           ( action == "RIGHT" && !getitem[selected] ) ||
                           ( action == "LEFT" && getitem[selected] )
                       ) ) {
                idx = selected;
            } else if( action == "ANY_INPUT" && raw_input_char == '`' ) {
                std::string ext = string_input_popup(
                                      _( "Enter 2 letters (case sensitive):" ), 3, "", "", "", 2 );
                if( ext.size() == 2 ) {
                    int p1 = pickup_chars.find( ext.at( 0 ) );
                    int p2 = pickup_chars.find( ext.at( 1 ) );
                    if( p1 != -1 && p2 != -1 ) {
                        idx = pickup_chars.size() + ( p1 * pickup_chars.size() ) + p2;
                    }
                }
            } else if( action == "ANY_INPUT" ) {
                idx = ( raw_input_char <= 127 ) ? pickup_chars.find( raw_input_char ) : -1;
                iScrollPos = 0;
            }

            if( idx >= 0 && idx < ( int )here.size() ) {
                if( getitem[idx] ) {
                    if( here[idx].count_by_charges() ) {
                        if( getitem[idx].count == 0 ) {
                            pl_copy.inv.find_item( getitem[idx].position ).charges -= here[idx].charges;
                        } else {
                            pl_copy.inv.find_item( getitem[idx].position ).charges -= getitem[idx].count;
                        }
                    } else {
                        unsigned stack_size = pl_copy.inv.const_stack( getitem[idx].position ).size();
                        pl_copy.i_rem( getitem[idx].position );
                        //if the stack_was emptied, removing the item invalidated later positions- fix them
                        if( stack_size == 1 ) {
                            for( unsigned i = 0; i < here.size(); i++ ) {
                                if( getitem[i] && getitem[i].position > getitem[idx].position ) {
                                    getitem[i].position--;
                                }
                            }
                        }
                    }
                } //end if getitem[idx]

                if( itemcount != 0 || getitem[idx].count == 0 ) {
                    if( itemcount >= here[idx].charges || !here[idx].count_by_charges() ) {
                        // Ignore the count if we pickup the whole stack anyway
                        // or something that is not counted by charges (tools)
                        itemcount = 0;
                    }
                    getitem[idx].count = itemcount;
                    itemcount = 0;
                }

                // Note: this might not change the value of getitem[idx] at all!
                getitem[idx].pick = ( action == "RIGHT" ? true : ( action == "LEFT" ? false : !getitem[idx] ) );
                if( action != "RIGHT" && action != "LEFT" ) {
                    selected = idx;
                    start = ( int )( idx / maxitems ) * maxitems;
                }

                if( getitem[idx] ) {
                    item temp = here[idx];
                    if( getitem[idx].count != 0 &&
                        getitem[idx].count < here[idx].charges ) {
                        temp.charges = getitem[idx].count;
                    }
                    item *added = &( pl_copy.i_add( temp ) );
                    getitem[idx].position = pl_copy.inv.position_by_item( added );
                } else {
                    getitem[idx].count = 0;
                }
                update = true;
            }

            werase( w_item_info );
            if( selected >= 0 && selected <= ( int )here.size() - 1 ) {
                std::vector<iteminfo> vThisItem, vDummy;
                here[selected].info( true, vThisItem );

                draw_item_info( w_item_info, "", "", vThisItem, vDummy, iScrollPos, true, true );
            }
            draw_custom_border( w_item_info, false );
            mvwprintw( w_item_info, 0, 2, "< " );
            trim_and_print( w_item_info, 0, 4, itemsW - 8, c_white, "%s >",
                            here[selected].display_name().c_str() );
            wrefresh( w_item_info );

            if( action == "SELECT_ALL" ) {
                int count = 0;
                for( size_t i = 0; i < here.size(); i++ ) {
                    if( getitem[i] ) {
                        count++;
                    } else {
                        item *added = &( pl_copy.i_add( here[i] ) );
                        getitem[i].position = pl_copy.inv.position_by_item( added );
                    }
                    getitem[i].pick = true;
                }
                if( count == ( int )here.size() ) {
                    for( size_t i = 0; i < here.size(); i++ ) {
                        getitem[i].pick = false;
                    }
                    pl_copy = g->u;
                    pl_copy.set_fake( true );
                }
                update = true;
            }

            for( cur_it = start; cur_it < start + maxitems; cur_it++ ) {
                mvwprintw( w_pickup, 1 + ( cur_it % maxitems ), 0,
                           "                                        " );
                if( cur_it < ( int )here.size() ) {
                    nc_color icolor = here[cur_it].color_in_inventory();
                    if( cur_it == selected ) {
                        icolor = hilite( icolor );
                    }

                    if( cur_it < ( int )pickup_chars.size() ) {
                        mvwputch( w_pickup, 1 + ( cur_it % maxitems ), 0, icolor,
                                  char( pickup_chars[cur_it] ) );
                    } else if( cur_it < ( int )pickup_chars.size() + ( int )pickup_chars.size() *
                               ( int )pickup_chars.size() ) {
                        int p = cur_it - pickup_chars.size();
                        int p1 = p / pickup_chars.size();
                        int p2 = p % pickup_chars.size();
                        mvwprintz( w_pickup, 1 + ( cur_it % maxitems ), 0, icolor, "`%c%c",
                                   char( pickup_chars[p1] ), char( pickup_chars[p2] ) );
                    } else {
                        mvwputch( w_pickup, 1 + ( cur_it % maxitems ), 0, icolor, ' ' );
                    }
                    if( getitem[cur_it] ) {
                        if( getitem[cur_it].count == 0 ) {
                            wprintz( w_pickup, c_ltblue, " + " );
                        } else {
                            wprintz( w_pickup, c_ltblue, " # " );
                        }
                    } else {
                        wprintw( w_pickup, " - " );
                    }
                    std::string item_name = here[cur_it].display_name();
                    if( OPTIONS["ITEM_SYMBOLS"] ) {
                        item_name = string_format( "%s %s", here[cur_it].symbol().c_str(),
                                                   item_name.c_str() );
                    }
                    trim_and_print( w_pickup, 1 + ( cur_it % maxitems ), 6, pickupW - 4, icolor,
                                    "%s", item_name.c_str() );
                }
            }

            mvwprintw( w_pickup, maxitems + 1, 0, _( "[%s] Unmark" ),
                       ctxt.get_desc( "LEFT", 1 ).c_str() );

            center_print( w_pickup, maxitems + 1, c_ltgray, _( "[%s] Help" ),
                          ctxt.get_desc( "HELP_KEYBINDINGS", 1 ).c_str() );

            right_print( w_pickup, maxitems + 1, 0, c_ltgray, _( "[%s] Mark" ),
                         ctxt.get_desc( "RIGHT", 1 ).c_str() );

            mvwprintw( w_pickup, maxitems + 2, 0, _( "[%s] Prev" ),
                       ctxt.get_desc( "PREV_TAB", 1 ).c_str() );

            center_print( w_pickup, maxitems + 2, c_ltgray, _( "[%s] All" ),
                          ctxt.get_desc( "SELECT_ALL", 1 ).c_str() );

            right_print( w_pickup, maxitems + 2, 0, c_ltgray, _( "[%s] Next" ),
                         ctxt.get_desc( "NEXT_TAB", 1 ).c_str() );

            if( update ) { // Update weight & volume information
                update = false;
                for( int i = 9; i < pickupW; ++i ) {
                    mvwaddch( w_pickup, 0, i, ' ' );
                }
                mvwprintz( w_pickup, 0,  9,
                           ( pl_copy.weight_carried() > g->u.weight_capacity() ? c_red : c_white ),
                           _( "Wgt %.1f" ), convert_weight( pl_copy.weight_carried() ) + 0.05 ); // +0.05 to round up
                wprintz( w_pickup, c_white, "/%.1f", convert_weight( g->u.weight_capacity() ) );
                mvwprintz( w_pickup, 0, 24,
                           ( pl_copy.volume_carried() > g->u.volume_capacity() ? c_red : c_white ),
                           _( "Vol %d" ), pl_copy.volume_carried() );
                wprintz( w_pickup, c_white, "/%d", g->u.volume_capacity() );
            }
            wrefresh( w_pickup );

            action = ctxt.handle_input();
            raw_input_char = ctxt.get_raw_input().get_first_input();

        } while( action != "QUIT" && action != "CONFIRM" );

        bool item_selected = false;
        // Check if we have selected an item.
        for( auto selection : getitem ) {
            if( selection ) {
                item_selected = true;
            }
        }
        if( action != "CONFIRM" || !item_selected ) {
            w_pickupptr.reset();
            w_item_infoptr.reset();
            add_msg( _( "Never mind." ) );
            g->reenter_fullscreen();
            g->refresh_all();
            return;
        }
    }

    // At this point we've selected our items, register an activity to pick them up.
    g->u.assign_activity( ACT_PICKUP, 0 );
    g->u.activity.placement = pos - g->u.pos();
    g->u.activity.values.push_back( from_vehicle );
    if( min == -1 ) {
        // Auto pickup will need to auto resume since there can be several of them on the stack.
        g->u.activity.auto_resume = true;
    }
    std::reverse( getitem.begin(), getitem.end() );
    for( size_t i = 0; i < here.size(); i++ ) {
        if( getitem[i] ) {
            g->u.activity.values.push_back( i );
            g->u.activity.values.push_back( getitem[i].count );
        }
    }

    g->reenter_fullscreen();
}
Example #3
0
// Pick up items at (pos).
void Pickup::pick_up( const tripoint &pos, int min )
{
    int veh_root_part = 0;
    int cargo_part = -1;

    vehicle *veh = g->m.veh_at (pos, veh_root_part);
    bool from_vehicle = false;

    if( min != -1 ) {
        switch( interact_with_vehicle( veh, pos, veh_root_part ) ) {
        case DONE:
            return;
        case ITEMS_FROM_CARGO:
            cargo_part = veh->part_with_feature( veh_root_part, "CARGO", false );
            from_vehicle = cargo_part >= 0;
            break;
        case ITEMS_FROM_GROUND:
            // Nothing to change, default is to pick from ground anyway.
            break;
        }
    }

    if (g->m.has_flag("SEALED", pos)) {
        return;
    }

    //min == -1 is Autopickup
    if (!g->u.can_pickup(min != -1)) { // no message on autopickup (-1)
        return;
    }

    if( !from_vehicle ) {
        bool isEmpty = (g->m.i_at(pos).empty());

        // Hide the pickup window if this is a toilet and there's nothing here
        // but water.
        if ((!isEmpty) && g->m.furn(pos) == f_toilet) {
            isEmpty = true;
            for( auto maybe_water : g->m.i_at(pos) ) {
                if( maybe_water.typeId() != "water") {
                    isEmpty = false;
                    break;
                }
            }
        }

        if (isEmpty && (min != -1 || !OPTIONS["AUTO_PICKUP_ADJACENT"] )) {
            return;
        }
    }

    // which items are we grabbing?
    std::vector<item> here;
    if( from_vehicle ) {
        auto vehitems = veh->get_items(cargo_part);
        here.resize( vehitems.size() );
        std::copy( vehitems.begin(), vehitems.end(), here.begin() );
    } else {
        auto mapitems = g->m.i_at(pos);
        here.resize( mapitems.size() );
        std::copy( mapitems.begin(), mapitems.end(), here.begin() );
    }

    if (min == -1) {
        if( g->check_zone( "NO_AUTO_PICKUP", pos ) ) {
            here.clear();
        }

        // Recursively pick up adjacent items if that option is on.
        if( OPTIONS["AUTO_PICKUP_ADJACENT"] && g->u.pos() == pos ) {
            //Autopickup adjacent
            direction adjacentDir[8] = {NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, NORTHWEST};
            for( auto &elem : adjacentDir ) {

                tripoint apos = tripoint( direction_XY( elem ), 0 );
                apos += pos;

                if( g->m.has_flag( "SEALED", apos ) ) {
                    continue;
                }
                if( g->check_zone( "NO_AUTO_PICKUP", apos ) ) {
                    continue;
                }
                pick_up( apos, min );
            }
        }
    }

    // Not many items, just grab them
    if ((int)here.size() <= min && min != -1) {
        g->u.assign_activity( ACT_PICKUP, 0 );
        g->u.activity.placement = pos - g->u.pos();
        g->u.activity.values.push_back( from_vehicle );
        // Only one item means index is 0.
        g->u.activity.values.push_back( 0 );
        // auto-pickup means pick up all.
        g->u.activity.values.push_back( 0 );
        return;
    }

    if(min != -1) { // don't bother if we're just autopickup-ing
        g->temp_exit_fullscreen();
    }
    bool sideStyle = use_narrow_sidebar();

    // Otherwise, we have Autopickup, 2 or more items and should list them, etc.
    int maxmaxitems = sideStyle ? TERMY : getmaxy(g->w_messages) - 3;

    int itemsH = std::min(25, TERMY / 2);
    int pickupBorderRows = 3;

    // The pickup list may consume the entire terminal, minus space needed for its
    // header/footer and the item info window.
    int minleftover = itemsH + pickupBorderRows;
    if(maxmaxitems > TERMY - minleftover) {
        maxmaxitems = TERMY - minleftover;
    }

    const int minmaxitems = sideStyle ? 6 : 9;

    std::vector<bool> getitem;
    getitem.resize(here.size(), false);

    int maxitems = here.size();
    maxitems = (maxitems < minmaxitems ? minmaxitems : (maxitems > maxmaxitems ? maxmaxitems :
                maxitems ));

    int itemcount = 0;
    std::map<int, unsigned int> pickup_count; // Count of how many we'll pick up from each stack

    if (min == -1) { //Auto Pickup, select matching items
        if( !select_autopickup_items( here, getitem) ) {
            // If we didn't find anything, bail out now.
            return;
        }
    } else {
        int pickupH = maxitems + pickupBorderRows;
        int pickupW = getmaxx(g->w_messages);
        int pickupY = VIEW_OFFSET_Y;
        int pickupX = getbegx(g->w_messages);

        int itemsW = pickupW;
        int itemsY = sideStyle ? pickupY + pickupH : TERMY - itemsH;
        int itemsX = pickupX;

        WINDOW *w_pickup    = newwin(pickupH, pickupW, pickupY, pickupX);
        WINDOW *w_item_info = newwin(itemsH,  itemsW,  itemsY,  itemsX);
        WINDOW_PTR w_pickupptr( w_pickup );
        WINDOW_PTR w_item_infoptr( w_item_info );

        int ch = ' ';
        int start = 0, cur_it;
        int new_weight = g->u.weight_carried(), new_volume = g->u.volume_carried();
        bool update = true;
        mvwprintw(w_pickup, 0, 0, _("PICK UP"));
        int selected = 0;
        int iScrollPos = 0;

        if(g->was_fullscreen) {
            g->draw_ter();
        }
        // Now print the two lists; those on the ground and about to be added to inv
        // Continue until we hit return or space
        do {
            static const std::string pickup_chars =
                "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:;";
            int idx = -1;
            for (int i = 1; i < pickupH; i++) {
                mvwprintw(w_pickup, i, 0,
                          "                                                ");
            }
            if (ch >= '0' && ch <= '9') {
                ch = (char)ch - '0';
                itemcount *= 10;
                itemcount += ch;
                if( itemcount < 0 ) {
                    itemcount = 0;
                }
            } else if ( ch == KEY_PPAGE) {
                iScrollPos--;
            } else if ( ch == KEY_NPAGE) {
                iScrollPos++;
            } else if ( ch == '<' ) {
                if ( start > 0 ) {
                    start -= maxitems;
                } else {
                    start = (int)( (here.size()-1) / maxitems ) * maxitems;
                }
                selected = start;
                mvwprintw(w_pickup, maxitems + 2, 0, "         ");
            } else if ( ch == '>' ) {
                if ( start + maxitems < (int)here.size() ) {
                    start += maxitems;
                } else {
                    start = 0;
                }
                iScrollPos = 0;
                selected = start;
                mvwprintw(w_pickup, maxitems + 2, pickupH, "            ");
            } else if ( ch == KEY_UP ) {
                selected--;
                iScrollPos = 0;
                if ( selected < 0 ) {
                    selected = here.size() - 1;
                    start = (int)( here.size() / maxitems ) * maxitems;
                    if (start >= (int)here.size()) {
                        start -= maxitems;
                    }
                } else if ( selected < start ) {
                    start -= maxitems;
                }
            } else if ( ch == KEY_DOWN ) {
                selected++;
                iScrollPos = 0;
                if ( selected >= (int)here.size() ) {
                    selected = 0;
                    start = 0;
                } else if ( selected >= start + maxitems ) {
                    start += maxitems;
                }
            } else if ( selected >= 0 && (
                            ( ch == KEY_RIGHT && !getitem[selected]) ||
                            ( ch == KEY_LEFT && getitem[selected] )
                        ) ) {
                idx = selected;
            } else if ( ch == '`' ) {
                std::string ext = string_input_popup(
                                      _("Enter 2 letters (case sensitive):"), 3, "", "", "", 2);
                if(ext.size() == 2) {
                    int p1 = pickup_chars.find(ext.at(0));
                    int p2 = pickup_chars.find(ext.at(1));
                    if ( p1 != -1 && p2 != -1 ) {
                        idx = pickup_chars.size() + ( p1 * pickup_chars.size() ) + p2;
                    }
                }
            } else {
                idx = ( ch <= 127 ) ? pickup_chars.find(ch) : -1;
                iScrollPos = 0;
            }

            if( idx >= 0 && idx < (int)here.size()) {
                if( getitem[idx] ) {
                    if( pickup_count[idx] != 0 && (int)pickup_count[idx] < here[idx].charges ) {
                        item temp = here[idx];
                        temp.charges = pickup_count[idx];
                        new_weight -= temp.weight();
                        new_volume -= temp.volume();
                    } else {
                        new_weight -= here[idx].weight();
                        new_volume -= here[idx].volume();
                    }
                }
                if (itemcount != 0 || pickup_count[idx] == 0) {
                    if (itemcount >= here[idx].charges || !here[idx].count_by_charges()) {
                        // Ignore the count if we pickup the whole stack anyway
                        // or something that is not counted by charges (tools)
                        itemcount = 0;
                    }
                    pickup_count[idx] = itemcount;
                    itemcount = 0;
                }

                // Note: this might not change the value of getitem[idx] at all!
                getitem[idx] = ( ch == KEY_RIGHT ? true : ( ch == KEY_LEFT ? false : !getitem[idx] ) );
                if ( ch != KEY_RIGHT && ch != KEY_LEFT) {
                    selected = idx;
                    start = (int)( idx / maxitems ) * maxitems;
                }

                if (getitem[idx]) {
                    if (pickup_count[idx] != 0 &&
                        (int)pickup_count[idx] < here[idx].charges) {
                        item temp = here[idx];
                        temp.charges = pickup_count[idx];
                        new_weight += temp.weight();
                        new_volume += temp.volume();
                    } else {
                        new_weight += here[idx].weight();
                        new_volume += here[idx].volume();
                    }
                } else {
                    pickup_count[idx] = 0;
                }
                update = true;
            }

            werase(w_item_info);
            if ( selected >= 0 && selected <= (int)here.size() - 1 ) {
                std::vector<iteminfo> vThisItem, vDummy;
                here[selected].info(true, vThisItem);

                draw_item_info(w_item_info, "", "", vThisItem, vDummy, iScrollPos, true, true);
            }
            draw_custom_border(w_item_info, false);
            mvwprintw(w_item_info, 0, 2, "< ");
            trim_and_print(w_item_info, 0, 4, itemsW - 8, c_white, "%s >", here[selected].display_name().c_str());
            wrefresh(w_item_info);

            if (ch == ',') {
                int count = 0;
                for (size_t i = 0; i < here.size(); i++) {
                    if (getitem[i]) {
                        count++;
                    } else {
                        new_weight += here[i].weight();
                        new_volume += here[i].volume();
                    }
                    getitem[i] = true;
                }
                if (count == (int)here.size()) {
                    for (size_t i = 0; i < here.size(); i++) {
                        getitem[i] = false;
                    }
                    new_weight = g->u.weight_carried();
                    new_volume = g->u.volume_carried();
                }
                update = true;
            }

            for (cur_it = start; cur_it < start + maxitems; cur_it++) {
                mvwprintw(w_pickup, 1 + (cur_it % maxitems), 0,
                          "                                        ");
                if (cur_it < (int)here.size()) {
                    nc_color icolor = here[cur_it].color_in_inventory();
                    if (cur_it == selected) {
                        icolor = hilite(icolor);
                    }

                    if (cur_it < (int)pickup_chars.size() ) {
                        mvwputch(w_pickup, 1 + (cur_it % maxitems), 0, icolor,
                                 char(pickup_chars[cur_it]));
                    } else {
                        int p = cur_it - pickup_chars.size();
                        int p1 = p / pickup_chars.size();
                        int p2 = p % pickup_chars.size();
                        mvwprintz(w_pickup, 1 + (cur_it % maxitems), 0, icolor, "`%c%c",
                                  char(pickup_chars[p1]), char(pickup_chars[p2]));
                    }
                    if (getitem[cur_it]) {
                        if (pickup_count[cur_it] == 0) {
                            wprintz(w_pickup, c_ltblue, " + ");
                        } else {
                            wprintz(w_pickup, c_ltblue, " # ");
                        }
                    } else {
                        wprintw(w_pickup, " - ");
                    }
                    std::string item_name = here[cur_it].display_name();
                    if (OPTIONS["ITEM_SYMBOLS"]) {
                        item_name = string_format("%c %s", here[cur_it].symbol(), item_name.c_str());
                    }
                    trim_and_print(w_pickup, 1 + (cur_it % maxitems), 6, pickupW - 4, icolor,
                                   "%s", item_name.c_str());
                }
            }

            int pw = pickupW;
            const char *unmark = _("[left] Unmark");
            const char *scroll = _("[up/dn] Scroll");
            const char *mark   = _("[right] Mark");
            mvwprintw(w_pickup, maxitems + 1, 0,                         unmark);
            mvwprintw(w_pickup, maxitems + 1, (pw - std::strlen(scroll)) / 2, scroll);
            mvwprintw(w_pickup, maxitems + 1,  pw - std::strlen(mark),        mark);
            const char *prev = _("[<] Prev");
            const char *all = _("[,] All");
            const char *next   = _("[>] Next");
            mvwprintw(w_pickup, maxitems + 2, 0, prev);
            mvwprintw(w_pickup, maxitems + 2, (pw - std::strlen(all)) / 2, all);
            mvwprintw(w_pickup, maxitems + 2, pw - std::strlen(next), next);

            if (update) { // Update weight & volume information
                update = false;
                for (int i = 9; i < pickupW; ++i) {
                    mvwaddch(w_pickup, 0, i, ' ');
                }
                mvwprintz(w_pickup, 0,  9,
                          (new_weight > g->u.weight_capacity() ? c_red : c_white),
                          _("Wgt %.1f"), g->u.convert_weight(new_weight) + 0.05); // +0.05 to round up
                wprintz(w_pickup, c_white, "/%.1f", g->u.convert_weight(g->u.weight_capacity()));
                mvwprintz(w_pickup, 0, 24,
                          (new_volume > g->u.volume_capacity() ? c_red : c_white),
                          _("Vol %d"), new_volume);
                wprintz(w_pickup, c_white, "/%d", g->u.volume_capacity());
            }
            wrefresh(w_pickup);

            ch = (int)getch();

        } while (ch != ' ' && ch != '\n' && ch != KEY_ENTER && ch != KEY_ESCAPE);

        bool item_selected = false;
        // Check if we have selected an item.
        for( auto selection : getitem ) {
            if( selection ) {
                item_selected = true;
            }
        }
        if( (ch != '\n' && ch != KEY_ENTER) || !item_selected ) {
            w_pickupptr.reset();
            w_item_infoptr.reset();
            add_msg(_("Never mind."));
            g->reenter_fullscreen();
            g->refresh_all();
            return;
        }
    }

    // At this point we've selected our items, register an activity to pick them up.
    g->u.assign_activity( ACT_PICKUP, 0 );
    g->u.activity.placement = pos - g->u.pos();
    g->u.activity.values.push_back( from_vehicle );
    if( min == -1 ) {
        // Auto pickup will need to auto resume since there can be several of them on the stack.
        g->u.activity.auto_resume = true;
    }
    for (size_t i = 0; i < here.size(); i++) {
        if( getitem[i] ) {
            g->u.activity.values.push_back( i );
            g->u.activity.values.push_back( pickup_count[i] );
        }
    }

    g->reenter_fullscreen();
}
Example #4
0
// Pick up items at (pos).
void Pickup::pick_up( const tripoint &pos, int min )
{
    int cargo_part = -1;

    const optional_vpart_position vp = g->m.veh_at( pos );
    vehicle *const veh = veh_pointer_or_null( vp );
    bool from_vehicle = false;

    if( min != -1 ) {
        switch( interact_with_vehicle( veh, pos, vp ? vp->part_index() : -1 ) ) {
            case DONE:
                return;
            case ITEMS_FROM_CARGO: {
                const cata::optional<vpart_reference> carg = vp.part_with_feature( "CARGO", false );
                cargo_part = carg ? carg->part_index() : -1;
            }
            from_vehicle = cargo_part >= 0;
            break;
            case ITEMS_FROM_GROUND:
                // Nothing to change, default is to pick from ground anyway.
                if( g->m.has_flag( "SEALED", pos ) ) {
                    return;
                }

                break;
        }
    }

    if( !from_vehicle ) {
        bool isEmpty = ( g->m.i_at( pos ).empty() );

        // Hide the pickup window if this is a toilet and there's nothing here
        // but water.
        if( ( !isEmpty ) && g->m.furn( pos ) == f_toilet ) {
            isEmpty = true;
            for( auto maybe_water : g->m.i_at( pos ) ) {
                if( maybe_water.typeId() != "water" ) {
                    isEmpty = false;
                    break;
                }
            }
        }

        if( isEmpty && ( min != -1 || !get_option<bool>( "AUTO_PICKUP_ADJACENT" ) ) ) {
            return;
        }
    }

    // which items are we grabbing?
    std::vector<item> here;
    if( from_vehicle ) {
        auto vehitems = veh->get_items( cargo_part );
        here.resize( vehitems.size() );
        std::copy( vehitems.begin(), vehitems.end(), here.begin() );
    } else {
        auto mapitems = g->m.i_at( pos );
        here.resize( mapitems.size() );
        std::copy( mapitems.begin(), mapitems.end(), here.begin() );
    }

    if( min == -1 ) {
        // Recursively pick up adjacent items if that option is on.
        if( get_option<bool>( "AUTO_PICKUP_ADJACENT" ) && g->u.pos() == pos ) {
            //Autopickup adjacent
            direction adjacentDir[8] = {NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, NORTHWEST};
            for( auto &elem : adjacentDir ) {

                tripoint apos = tripoint( direction_XY( elem ), 0 );
                apos += pos;

                pick_up( apos, min );
            }
        }

        // Bail out if this square cannot be auto-picked-up
        if( g->check_zone( zone_type_id( "NO_AUTO_PICKUP" ), pos ) ) {
            return;
        } else if( g->m.has_flag( "SEALED", pos ) ) {
            return;
        }
    }

    // Not many items, just grab them
    if( ( int )here.size() <= min && min != -1 ) {
        g->u.assign_activity( activity_id( "ACT_PICKUP" ) );
        g->u.activity.placement = pos - g->u.pos();
        g->u.activity.values.push_back( from_vehicle );
        // Only one item means index is 0.
        g->u.activity.values.push_back( 0 );
        // auto-pickup means pick up all.
        g->u.activity.values.push_back( 0 );
        return;
    }

    std::vector<std::list<item_idx>> stacked_here;
    for( size_t i = 0; i < here.size(); i++ ) {
        item &it = here[i];
        bool found_stack = false;
        for( auto &stack : stacked_here ) {
            if( stack.begin()->_item.stacks_with( it ) ) {
                item_idx el = { it, i };
                stack.push_back( el );
                found_stack = true;
                break;
            }
        }
        if( !found_stack ) {
            std::list<item_idx> newstack;
            newstack.push_back( { it, i } );
            stacked_here.push_back( newstack );
        }
    }
    std::reverse( stacked_here.begin(), stacked_here.end() );

    if( min != -1 ) { // don't bother if we're just autopickuping
        g->temp_exit_fullscreen();
    }
    bool sideStyle = use_narrow_sidebar();

    // Otherwise, we have Autopickup, 2 or more items and should list them, etc.
    int maxmaxitems = sideStyle ? TERMY : getmaxy( g->w_messages ) - 3;

    int itemsH = std::min( 25, TERMY / 2 );
    int pickupBorderRows = 3;

    // The pickup list may consume the entire terminal, minus space needed for its
    // header/footer and the item info window.
    int minleftover = itemsH + pickupBorderRows;
    if( maxmaxitems > TERMY - minleftover ) {
        maxmaxitems = TERMY - minleftover;
    }

    const int minmaxitems = sideStyle ? 6 : 9;

    std::vector<pickup_count> getitem( stacked_here.size() );

    int maxitems = stacked_here.size();
    maxitems = ( maxitems < minmaxitems ? minmaxitems : ( maxitems > maxmaxitems ? maxmaxitems :
                 maxitems ) );

    int itemcount = 0;

    if( min == -1 ) { //Auto Pickup, select matching items
        if( !select_autopickup_items( stacked_here, getitem ) ) {
            // If we didn't find anything, bail out now.
            return;
        }
    } else {
        int pickupH = maxitems + pickupBorderRows;
        int pickupW = getmaxx( g->w_messages );
        int pickupY = VIEW_OFFSET_Y;
        int pickupX = getbegx( g->w_messages );

        int itemsW = pickupW;
        int itemsY = sideStyle ? pickupY + pickupH : TERMY - itemsH;
        int itemsX = pickupX;

        catacurses::window w_pickup = catacurses::newwin( pickupH, pickupW, pickupY, pickupX );
        catacurses::window w_item_info = catacurses::newwin( itemsH,  itemsW,  itemsY,  itemsX );

        std::string action;
        long raw_input_char = ' ';
        input_context ctxt( "PICKUP" );
        ctxt.register_action( "UP" );
        ctxt.register_action( "DOWN" );
        ctxt.register_action( "RIGHT" );
        ctxt.register_action( "LEFT" );
        ctxt.register_action( "NEXT_TAB", _( "Next page" ) );
        ctxt.register_action( "PREV_TAB", _( "Previous page" ) );
        ctxt.register_action( "SCROLL_UP" );
        ctxt.register_action( "SCROLL_DOWN" );
        ctxt.register_action( "CONFIRM" );
        ctxt.register_action( "SELECT_ALL" );
        ctxt.register_action( "QUIT", _( "Cancel" ) );
        ctxt.register_action( "ANY_INPUT" );
        ctxt.register_action( "HELP_KEYBINDINGS" );
        ctxt.register_action( "FILTER" );

        int start = 0;
        int cur_it = 0;
        bool update = true;
        mvwprintw( w_pickup, 0, 0, _( "PICK UP" ) );
        int selected = 0;
        int iScrollPos = 0;

        std::string filter;
        std::string new_filter;
        std::vector<int> matches;//Indexes of items that match the filter
        bool filter_changed = true;
        if( g->was_fullscreen ) {
            g->draw_ter();
        }
        // Now print the two lists; those on the ground and about to be added to inv
        // Continue until we hit return or space
        do {
            const std::string pickup_chars =
                ctxt.get_available_single_char_hotkeys( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:;" );
            int idx = -1;
            for( int i = 1; i < pickupH; i++ ) {
                mvwprintw( w_pickup, i, 0,
                           "                                                " );
            }
            if( action == "ANY_INPUT" &&
                raw_input_char >= '0' && raw_input_char <= '9' ) {
                int raw_input_char_value = ( char )raw_input_char - '0';
                itemcount *= 10;
                itemcount += raw_input_char_value;
                if( itemcount < 0 ) {
                    itemcount = 0;
                }
            } else if( action == "SCROLL_UP" ) {
                iScrollPos--;
            } else if( action == "SCROLL_DOWN" ) {
                iScrollPos++;
            } else if( action == "PREV_TAB" ) {
                if( start > 0 ) {
                    start -= maxitems;
                } else {
                    start = ( int )( ( matches.size() - 1 ) / maxitems ) * maxitems;
                }
                selected = start;
                mvwprintw( w_pickup, maxitems + 2, 0, "         " );
            } else if( action == "NEXT_TAB" ) {
                if( start + maxitems < ( int )matches.size() ) {
                    start += maxitems;
                } else {
                    start = 0;
                }
                iScrollPos = 0;
                selected = start;
                mvwprintw( w_pickup, maxitems + 2, pickupH, "            " );
            } else if( action == "UP" ) {
                selected--;
                iScrollPos = 0;
                if( selected < 0 ) {
                    selected = matches.size() - 1;
                    start = ( int )( matches.size() / maxitems ) * maxitems;
                    if( start >= ( int )matches.size() ) {
                        start -= maxitems;
                    }
                } else if( selected < start ) {
                    start -= maxitems;
                }
            } else if( action == "DOWN" ) {
                selected++;
                iScrollPos = 0;
                if( selected >= ( int )matches.size() ) {
                    selected = 0;
                    start = 0;
                } else if( selected >= start + maxitems ) {
                    start += maxitems;
                }
            } else if( selected >= 0 && selected < int( matches.size() ) &&
                       ( ( action == "RIGHT" && !getitem[matches[selected]].pick ) ||
                         ( action == "LEFT" && getitem[matches[selected]].pick ) ) ) {
                idx = selected;
            } else if( action == "FILTER" ) {
                new_filter = filter;
                string_input_popup popup;
                popup
                .title( _( "Set filter" ) )
                .width( 30 )
                .edit( new_filter );
                if( !popup.canceled() ) {
                    filter_changed = true;
                } else {
                    wrefresh( g->w_terrain );
                }
            } else if( action == "ANY_INPUT" && raw_input_char == '`' ) {
                std::string ext = string_input_popup()
                                  .title( _( "Enter 2 letters (case sensitive):" ) )
                                  .width( 3 )
                                  .max_length( 2 )
                                  .query_string();
                if( ext.size() == 2 ) {
                    int p1 = pickup_chars.find( ext.at( 0 ) );
                    int p2 = pickup_chars.find( ext.at( 1 ) );
                    if( p1 != -1 && p2 != -1 ) {
                        idx = pickup_chars.size() + ( p1 * pickup_chars.size() ) + p2;
                    }
                }
            } else if( action == "ANY_INPUT" ) {
                idx = ( raw_input_char <= 127 ) ? pickup_chars.find( raw_input_char ) : -1;
                iScrollPos = 0;
            }

            if( idx >= 0 && idx < ( int )matches.size() ) {
                size_t true_idx = matches[idx];
                if( itemcount != 0 || getitem[true_idx].count == 0 ) {
                    item &temp = stacked_here[true_idx].begin()->_item;
                    int amount_available = temp.count_by_charges() ? temp.charges : stacked_here[true_idx].size();
                    if( itemcount >= amount_available ) {
                        itemcount = 0;
                    }
                    getitem[true_idx].count = itemcount;
                    itemcount = 0;
                }

                // Note: this might not change the value of getitem[idx] at all!
                getitem[true_idx].pick = ( action == "RIGHT" ? true :
                                           ( action == "LEFT" ? false :
                                             !getitem[true_idx].pick ) );
                if( action != "RIGHT" && action != "LEFT" ) {
                    selected = idx;
                    start = ( int )( idx / maxitems ) * maxitems;
                }

                if( !getitem[true_idx].pick ) {
                    getitem[true_idx].count = 0;
                }
                update = true;
            }
            if( filter_changed ) {
                matches.clear();
                while( matches.empty() ) {
                    auto filter_func = item_filter_from_string( new_filter );
                    for( size_t index = 0; index < stacked_here.size(); index++ ) {
                        if( filter_func( stacked_here[index].begin()->_item ) ) {
                            matches.push_back( index );
                        }
                    }
                    if( matches.empty() ) {
                        popup( _( "Your filter returned no results" ) );
                        wrefresh( g->w_terrain );
                        // The filter must have results, or simply be emptied or canceled,
                        // as this screen can't be reached without there being
                        // items available
                        string_input_popup popup;
                        popup
                        .title( _( "Set filter" ) )
                        .width( 30 )
                        .edit( new_filter );
                        if( popup.canceled() ) {
                            new_filter = filter;
                            filter_changed = false;
                        }
                    }
                }
                if( filter_changed ) {
                    filter = new_filter;
                    filter_changed = false;
                    selected = 0;
                    start = 0;
                    iScrollPos = 0;
                }
                wrefresh( g->w_terrain );
            }
            item &selected_item = stacked_here[matches[selected]].begin()->_item;

            werase( w_item_info );
            if( selected >= 0 && selected <= ( int )stacked_here.size() - 1 ) {
                std::vector<iteminfo> vThisItem;
                std::vector<iteminfo> vDummy;
                selected_item.info( true, vThisItem );

                draw_item_info( w_item_info, "", "", vThisItem, vDummy, iScrollPos, true, true );
            }
            draw_custom_border( w_item_info, false );
            mvwprintw( w_item_info, 0, 2, "< " );
            trim_and_print( w_item_info, 0, 4, itemsW - 8, c_white, "%s >",
                            selected_item.display_name().c_str() );
            wrefresh( w_item_info );

            if( action == "SELECT_ALL" ) {
                int count = 0;
                for( auto i : matches ) {
                    if( getitem[i].pick ) {
                        count++;
                    }
                    getitem[i].pick = true;
                }
                if( count == ( int )stacked_here.size() ) {
                    for( size_t i = 0; i < stacked_here.size(); i++ ) {
                        getitem[i].pick = false;
                    }
                }
                update = true;
            }
            for( cur_it = start; cur_it < start + maxitems; cur_it++ ) {
                mvwprintw( w_pickup, 1 + ( cur_it % maxitems ), 0,
                           "                                        " );
                if( cur_it < ( int )matches.size() ) {
                    int true_it = matches[cur_it];
                    item &this_item = stacked_here[ true_it ].begin()->_item;
                    nc_color icolor = this_item.color_in_inventory();
                    if( cur_it == selected ) {
                        icolor = hilite( icolor );
                    }

                    if( cur_it < ( int )pickup_chars.size() ) {
                        mvwputch( w_pickup, 1 + ( cur_it % maxitems ), 0, icolor,
                                  char( pickup_chars[cur_it] ) );
                    } else if( cur_it < ( int )pickup_chars.size() + ( int )pickup_chars.size() *
                               ( int )pickup_chars.size() ) {
                        int p = cur_it - pickup_chars.size();
                        int p1 = p / pickup_chars.size();
                        int p2 = p % pickup_chars.size();
                        mvwprintz( w_pickup, 1 + ( cur_it % maxitems ), 0, icolor, "`%c%c",
                                   char( pickup_chars[p1] ), char( pickup_chars[p2] ) );
                    } else {
                        mvwputch( w_pickup, 1 + ( cur_it % maxitems ), 0, icolor, ' ' );
                    }
                    if( getitem[true_it].pick ) {
                        if( getitem[true_it].count == 0 ) {
                            wprintz( w_pickup, c_light_blue, " + " );
                        } else {
                            wprintz( w_pickup, c_light_blue, " # " );
                        }
                    } else {
                        wprintw( w_pickup, " - " );
                    }
                    std::string item_name;
                    if( stacked_here[true_it].begin()->_item.ammo_type() == "money" ) {
                        //Count charges
                        //TODO: transition to the item_location system used for the inventory
                        unsigned long charges_total = 0;
                        for( const auto item : stacked_here[true_it] ) {
                            charges_total += item._item.charges;
                        }
                        //Picking up none or all the cards in a stack
                        if( !getitem[true_it].pick || getitem[true_it].count == 0 ) {
                            item_name = stacked_here[true_it].begin()->_item.display_money( stacked_here[true_it].size(),
                                        charges_total );
                        } else {
                            unsigned long charges = 0;
                            int c = getitem[true_it].count;
                            for( auto it = stacked_here[true_it].begin(); it != stacked_here[true_it].end() &&
                                 c > 0; ++it, --c ) {
                                charges += it->_item.charges;
                            }
                            item_name = string_format( _( "%s of %s" ),
                                                       stacked_here[true_it].begin()->_item.display_money( getitem[true_it].count, charges ),
                                                       format_money( charges_total ) );
                        }
                    } else {
                        item_name = this_item.display_name( stacked_here[true_it].size() );
                    }
                    if( stacked_here[true_it].size() > 1 ) {
                        item_name = string_format( "%d %s", stacked_here[true_it].size(), item_name.c_str() );
                    }
                    if( get_option<bool>( "ITEM_SYMBOLS" ) ) {
                        item_name = string_format( "%s %s", this_item.symbol().c_str(),
                                                   item_name.c_str() );
                    }
                    trim_and_print( w_pickup, 1 + ( cur_it % maxitems ), 6, pickupW - 4, icolor,
                                    item_name );
                }
            }

            mvwprintw( w_pickup, maxitems + 1, 0, _( "[%s] Unmark" ),
                       ctxt.get_desc( "LEFT", 1 ).c_str() );

            center_print( w_pickup, maxitems + 1, c_light_gray, string_format( _( "[%s] Help" ),
                          ctxt.get_desc( "HELP_KEYBINDINGS", 1 ).c_str() ) );

            right_print( w_pickup, maxitems + 1, 0, c_light_gray, string_format( _( "[%s] Mark" ),
                         ctxt.get_desc( "RIGHT", 1 ).c_str() ) );

            mvwprintw( w_pickup, maxitems + 2, 0, _( "[%s] Prev" ),
                       ctxt.get_desc( "PREV_TAB", 1 ).c_str() );

            center_print( w_pickup, maxitems + 2, c_light_gray, string_format( _( "[%s] All" ),
                          ctxt.get_desc( "SELECT_ALL", 1 ).c_str() ) );

            right_print( w_pickup, maxitems + 2, 0, c_light_gray, string_format( _( "[%s] Next" ),
                         ctxt.get_desc( "NEXT_TAB", 1 ).c_str() ) );

            if( update ) { // Update weight & volume information
                update = false;
                for( int i = 9; i < pickupW; ++i ) {
                    mvwaddch( w_pickup, 0, i, ' ' );
                }
                units::mass weight_picked_up = 0;
                units::volume volume_picked_up = 0;
                for( size_t i = 0; i < getitem.size(); i++ ) {
                    if( getitem[i].pick ) {
                        item temp = stacked_here[i].begin()->_item;
                        if( temp.count_by_charges() && getitem[i].count < temp.charges && getitem[i].count != 0 ) {
                            temp.charges = getitem[i].count;
                        }
                        int num_picked = std::min( stacked_here[i].size(),
                                                   getitem[i].count == 0 ? stacked_here[i].size() : getitem[i].count );
                        weight_picked_up += temp.weight() * num_picked;
                        volume_picked_up += temp.volume() * num_picked;
                    }
                }

                auto weight_predict = g->u.weight_carried() + weight_picked_up;
                auto volume_predict = g->u.volume_carried() + volume_picked_up;

                mvwprintz( w_pickup, 0, 9, weight_predict > g->u.weight_capacity() ? c_red : c_white,
                           _( "Wgt %.1f" ), round_up( convert_weight( weight_predict ), 1 ) );

                wprintz( w_pickup, c_white, "/%.1f", round_up( convert_weight( g->u.weight_capacity() ), 1 ) );

                std::string fmted_volume_predict = format_volume( volume_predict );
                mvwprintz( w_pickup, 0, 24, volume_predict > g->u.volume_capacity() ? c_red : c_white,
                           _( "Vol %s" ), fmted_volume_predict.c_str() );

                std::string fmted_volume_capacity = format_volume( g->u.volume_capacity() );
                wprintz( w_pickup, c_white, "/%s", fmted_volume_capacity.c_str() );
            };

            wrefresh( w_pickup );

            action = ctxt.handle_input();
            raw_input_char = ctxt.get_raw_input().get_first_input();

        } while( action != "QUIT" && action != "CONFIRM" );

        bool item_selected = false;
        // Check if we have selected an item.
        for( auto selection : getitem ) {
            if( selection.pick ) {
                item_selected = true;
            }
        }
        if( action != "CONFIRM" || !item_selected ) {
            w_pickup = catacurses::window();
            w_item_info = catacurses::window();
            add_msg( _( "Never mind." ) );
            g->reenter_fullscreen();
            g->refresh_all();
            return;
        }
    }

    // At this point we've selected our items, register an activity to pick them up.
    g->u.assign_activity( activity_id( "ACT_PICKUP" ) );
    g->u.activity.placement = pos - g->u.pos();
    g->u.activity.values.push_back( from_vehicle );
    if( min == -1 ) {
        // Auto pickup will need to auto resume since there can be several of them on the stack.
        g->u.activity.auto_resume = true;
    }
    std::vector<std::pair<int, int>> pick_values;
    for( size_t i = 0; i < stacked_here.size(); i++ ) {
        const auto &selection = getitem[i];
        if( !selection.pick ) {
            continue;
        }

        const auto &stack = stacked_here[i];
        // Note: items can be both charged and stacked
        // For robustness, let's assume they can be both in the same stack
        bool pick_all = selection.count == 0;
        size_t count = selection.count;
        for( const item_idx &it : stack ) {
            if( !pick_all && count == 0 ) {
                break;
            }

            if( it._item.count_by_charges() ) {
                size_t num_picked = std::min( ( size_t )it._item.charges, count );
                pick_values.push_back( { static_cast<int>( it.idx ), static_cast<int>( num_picked ) } );
                count -= num_picked;
            } else {
                size_t num_picked = 1;
                pick_values.push_back( { static_cast<int>( it.idx ), 0 } );
                count -= num_picked;
            }
        }
    }
    // The pickup activity picks up items last-to-first from its values list, so make sure the
    // higher indices are at the end.
    std::sort( pick_values.begin(), pick_values.end() );
    for( auto &it : pick_values ) {
        g->u.activity.values.push_back( it.first );
        g->u.activity.values.push_back( it.second );
    }

    g->reenter_fullscreen();
}
Example #5
0
File: test.c Project: codl/ponyrl
int main(void){
    int input;
    int width, height;
    struct sigaction sa;
    sa.sa_handler =  &signalCatch;
    sa.sa_flags = 0;
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGQUIT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    screen_init();

    get_screen_size(&width, &height);

    srand((unsigned int)time(NULL));
    init_map();

    player.x = 1;
    player.y = 1;
    player.ele = 0;
    player.type = CREA_EARTH_PONY;
    player.inv = 0;
    player.health = 1;

    SQUARE(get_tile(0,0,0)->tile.sq, 1,1)->c = &player;

    struct item* spikes = malloc(sizeof(struct item));
    spikes->type = ITEM_HOOF_SPIKES;

    struct itemlist* a_list = malloc(sizeof(struct itemlist));
    a_list->item = spikes;
    a_list->next = 0;

    SQUARE(get_tile(0,0,0)->tile.sq, 4,2)->i = a_list;

    struct creature *earth_pony = malloc(sizeof(struct creature));
    earth_pony->type = 0;
    earth_pony->health = 5; /* test value */
    earth_pony->dex = 5;

    SQUARE(get_tile(0,0,0)->tile.sq, 3,3)->c = earth_pony;

    draw_map(1,1,0);

    while(1){
        input = getchar();
        switch(input){
            case 'h':
                move_player(W);
                break;
            case 'j':
                move_player(S);
                break;
            case 'k':
                move_player(N);
                break;
            case 'l':
                move_player(E);
                break;
            case 'y':
                move_player(NW);
                break;
            case 'u':
                move_player(NE);
                break;
            case 'n':
                move_player(SE);
                break;
            case 'b':
                move_player(SW);
                break;
            case ',':
                pick_up();
                break;
            case 'q':
                screen_free();
                return 0;
        }
    }
}
Example #6
0
File: object.c Project: atrinik/dwc
/**
 * /take command.
 * @param op Player.
 * @param params What to take.
 * @return 0. */
int command_take(object *op, char *params)
{
	object *tmp, *next;
	int did_one = 0, missed = 0, ival;

	if (!params)
	{
		new_draw_info(NDI_UNIQUE, op, "Take what?");
		return 0;
	}

	if (CONTR(op)->container)
	{
		tmp = CONTR(op)->container->inv;
	}
	else
	{
		tmp = GET_MAP_OB_LAST(op->map, op->x, op->y);
	}

	if (!tmp)
	{
		new_draw_info(NDI_UNIQUE, op, "Nothing to take.");
		return 0;
	}

	SET_FLAG(op, FLAG_NO_FIX_PLAYER);

	for ( ; tmp; tmp = next)
	{
		next = tmp->below;

		if ((tmp->layer != 3 && tmp->layer != 4) || QUERY_FLAG(tmp, FLAG_NO_PICK) || IS_SYS_INVISIBLE(tmp))
		{
			continue;
		}

		ival = item_matched_string(op, tmp, params);

		if (ival > 0)
		{
			if (ival <= 2 && !can_pick(op, tmp))
			{
				missed++;
			}
			else
			{
				pick_up(op, tmp);
				did_one = 1;
			}
		}
	}

	CLEAR_FLAG(op, FLAG_NO_FIX_PLAYER);

	if (did_one)
	{
		fix_player(op);
	}
	else if (!missed)
	{
		new_draw_info(NDI_UNIQUE, op, "Nothing to take.");
	}

	if (missed == 1)
	{
		new_draw_info(NDI_UNIQUE, op, "You were unable to take one of the items.");
	}
	else if (missed > 1)
	{
		new_draw_info_format(NDI_UNIQUE, op, "You were unable to take %d of the items.", missed);
	}

	if (op->type == PLAYER)
	{
		CONTR(op)->count = 0;
	}

	return 0;
}