예제 #1
0
void Pickup::do_pickup( const tripoint &pickup_target_arg, bool from_vehicle,
                        std::list<int> &indices, std::list<int> &quantities, bool autopickup )
{
    bool got_water = false;
    int cargo_part = -1;
    vehicle *veh = nullptr;
    bool weight_is_okay = ( g->u.weight_carried() <= g->u.weight_capacity() );
    bool volume_is_okay = ( g->u.volume_carried() <= g->u.volume_capacity() );
    bool offered_swap = false;
    // Convert from player-relative to map-relative.
    tripoint pickup_target = pickup_target_arg + g->u.pos();
    // Map of items picked up so we can output them all at the end and
    // merge dropping items with the same name.
    PickupMap mapPickup;

    if( from_vehicle ) {
        int veh_root_part = -1;
        veh = g->m.veh_at( pickup_target, veh_root_part );
        cargo_part = veh->part_with_feature( veh_root_part, "CARGO", false );
    }

    while( g->u.moves >= 0 && !indices.empty() ) {
        // Pulling from the back of the (in-order) list of indices insures
        // that we pull from the end of the vector.
        int index = indices.back();
        int quantity = quantities.back();
        // Whether we pick the item up or not, we're done trying to do so,
        // so remove it from the list.
        indices.pop_back();
        quantities.pop_back();

        item *target = nullptr;
        if( from_vehicle ) {
            target = g->m.item_from( veh, cargo_part, index );
        } else {
            target = g->m.item_from( pickup_target, index );
        }

        if( target == nullptr ) {
            continue; // No such item.
        }

        pick_one_up( pickup_target, *target, veh, cargo_part, index, quantity,
                     got_water, offered_swap, mapPickup, autopickup );
    }

    if( !mapPickup.empty() ) {
        show_pickup_message( mapPickup );
    }

    if( got_water ) {
        add_msg( m_info, _( "You can't pick up a liquid!" ) );
    }
    if( weight_is_okay && g->u.weight_carried() > g->u.weight_capacity() ) {
        add_msg( m_bad, _( "You're overburdened!" ) );
    }
    if( volume_is_okay && g->u.volume_carried() > g->u.volume_capacity() ) {
        add_msg( m_bad, _( "You struggle to carry such a large volume!" ) );
    }
}
예제 #2
0
void Pickup::do_pickup( point pickup_target, bool from_vehicle,
                        std::list<int> &indices, std::list<int> &quantities, bool autopickup )
{
    bool got_water = false;
    int cargo_part = -1;
    vehicle *veh = nullptr;
    bool weight_is_okay = (g->u.weight_carried() <= g->u.weight_capacity());
    bool volume_is_okay = (g->u.volume_carried() <= g->u.volume_capacity() -  2);
    bool offered_swap = false;
    // Convert from player-relative to map-relative.
    pickup_target.x += g->u.xpos();
    pickup_target.y += g->u.ypos();
    // Map of items picked up so we can output them all at the end and
    // merge dropping items with the same name.
    std::map<std::string, int> mapPickup;
    std::map<std::string, item> item_info;

    if( from_vehicle ) {
        int veh_root_part = -1;
        veh = g->m.veh_at( pickup_target.x, pickup_target.y, veh_root_part );
        cargo_part = veh->part_with_feature( veh_root_part, "CARGO", false );
    }

    std::vector<item> &here = from_vehicle ? veh->parts[cargo_part].items :
        g->m.i_at_mutable( pickup_target.x, pickup_target.y );

    // Grow here vector if needed to avoid resize operations invalidating pointers during operation.
    here.reserve( here.size() + 1 );

    while( g->u.moves >= 0 && !indices.empty() ) {
        // Pulling from the back of the (in-order) list of indices insures
        // that we pull from the end of the vector.
        int index = indices.back();
        int quantity = quantities.back();
        // Whether we pick the item up or not, we're done trying to do so,
        // so remove it from the list.
        indices.pop_back();
        quantities.pop_back();

        pick_one_up( pickup_target, here[index], veh, cargo_part, index, quantity,
                     got_water, offered_swap, mapPickup, item_info, autopickup );
    }

    if( !mapPickup.empty() ) {
        show_pickup_message(mapPickup, item_info);
    }

    if (got_water) {
        add_msg(m_info, _("You can't pick up a liquid!"));
    }
    if (weight_is_okay && g->u.weight_carried() >= g->u.weight_capacity()) {
        add_msg(m_bad, _("You're overburdened!"));
    }
    if (volume_is_okay && g->u.volume_carried() > g->u.volume_capacity() - 2) {
        add_msg(m_bad, _("You struggle to carry such a large volume!"));
    }
}
예제 #3
0
//helper function for Pickup::pick_up
//return value is amount of ammo added to quiver
int Pickup::handle_quiver_insertion(item &here, bool inv_on_fail, int &moves_to_decrement,
                                    bool &picked_up)
{
    //add ammo to quiver
    int quivered = here.add_ammo_to_quiver(&g->u, true);
    if(quivered > 0) {
        moves_to_decrement = 0; //moves already decremented in item::add_ammo_to_quiver()
        picked_up = true;
        return quivered;
    } else if (inv_on_fail) {
        //add to inventory instead
        g->u.i_add(here);
        picked_up = true;

        //display output message
        std::map<std::string, int> map_pickup;
        int charges = (here.count_by_charges()) ? here.charges : 1;
        map_pickup.insert(std::pair<std::string, int>(here.tname(), charges));
        show_pickup_message(map_pickup);
    }
    return 0;
}
예제 #4
0
void Pickup::pick_one_up( const tripoint &pickup_target, item &newit, vehicle *veh,
                          int cargo_part, int index, int quantity, bool &got_water,
                          bool &offered_swap, PickupMap &mapPickup, bool autopickup )
{
    int moves_taken = 100;
    bool picked_up = false;
    item leftovers = newit;

    if( newit.invlet != '\0' &&
        g->u.invlet_to_position( newit.invlet ) != INT_MIN ) {
        // Existing invlet is not re-usable, remove it and let the code in player.cpp/inventory.cpp
        // add a new invlet, otherwise keep the (usable) invlet.
        newit.invlet = '\0';
    }

    if( quantity != 0 && newit.count_by_charges() ) {
        // Reinserting leftovers happens after item removal to avoid stacking issues.
        leftovers.charges = newit.charges - quantity;
        if( leftovers.charges > 0 ) {
            newit.charges = quantity;
        }
    } else {
        leftovers.charges = 0;
    }

    if( newit.made_of(LIQUID) ) {
        got_water = true;
    } else if (!g->u.can_pickWeight(newit.weight(), false)) {
        add_msg(m_info, _("The %s is too heavy!"), newit.display_name().c_str());
    } else if( newit.is_ammo() && (newit.ammo_type() == "arrow" || newit.ammo_type() == "bolt")) {
        //add ammo to quiver
        int quivered = handle_quiver_insertion( newit, moves_taken, picked_up);
        if( newit.charges > 0) {
            if(!g->u.can_pickVolume( newit.volume())) {
                if(quivered > 0) {
                    //update the charges for the item that gets re-added to the game map
                    quantity = quivered;
                    leftovers.charges = newit.charges;
                }
                if( !autopickup ) {
                    // Silence some messaging if we're doing autopickup.
                    add_msg(m_info, ngettext("There's no room in your inventory for the %s.",
                                             "There's no room in your inventory for the %s.",
                                             newit.charges), newit.tname(newit.charges).c_str());
                }
            } else {
                //add to inventory instead
                item &it = g->u.i_add(newit);
                picked_up = true;

                //display output message
                PickupMap map_pickup;
                int charges = (newit.count_by_charges()) ? newit.charges : 1;
                map_pickup.insert(std::pair<std::string, ItemCount>(newit.tname(), ItemCount(it, charges)));
                show_pickup_message(map_pickup);
            }
        }
    } else if (!g->u.can_pickVolume(newit.volume())) {
        if( !autopickup ) {
            // Armor can be instantly worn
            if (newit.is_armor() &&
                query_yn(_("Put on the %s?"),
                         newit.display_name().c_str())) {
                if (g->u.wear_item(newit)) {
                    picked_up = true;
                }
            } else if (g->u.is_armed()) {
                if (!g->u.weapon.has_flag("NO_UNWIELD")) {
                    if( !offered_swap ) {
                        offered_swap = true;
                        if ( g->u.weapon.type->id != newit.type->id &&
                             query_yn(_("No space for %1$s; wield instead? (drops %2$s)"),
                                      newit.display_name().c_str(),
                                      g->u.weapon.display_name().c_str()) ) {
                            picked_up = true;
                            g->m.add_item_or_charges( pickup_target,
                                                      g->u.remove_weapon(), 1 );
                            g->u.inv.assign_empty_invlet( newit, true ); // force getting an invlet.
                            g->u.wield( &( g->u.i_add(newit) ) );

                            if (newit.invlet) {
                                add_msg(m_info, _("Wielding %c - %s"), newit.invlet,
                                        newit.display_name().c_str());
                            } else {
                                add_msg(m_info, _("Wielding - %s"), newit.display_name().c_str());
                            }
                        }
                    }
                } else {
                    add_msg(m_info, _("There's no room in your inventory for the %s "
                                      "and you can't unwield your %s."),
                            newit.display_name().c_str(),
                            g->u.weapon.display_name().c_str());
                }
            } else if( !g->u.is_armed()  ) {
                if (g->u.keep_hands_free) {
                    add_msg(m_info, _("There's no room in your inventory for the %s "
                                      "and you have decided to keep your hands free."),
                            newit.display_name().c_str());
                } else {
                    g->u.inv.assign_empty_invlet(newit, true);  // force getting an invlet.
                    g->u.wield(&(g->u.i_add(newit)));
                    picked_up = true;

                    if (newit.invlet) {
                        add_msg(m_info, _("Wielding %c - %s"), newit.invlet,
                                newit.display_name().c_str());
                    } else {
                        add_msg(m_info, _("Wielding - %s"), newit.display_name().c_str());
                    }
                }
            } // end of if unarmed
        } // end of if !autopickup
    } else {
        auto &entry = mapPickup[newit.tname()];
        entry.second += newit.count_by_charges() ? newit.charges : 1;
        entry.first = g->u.i_add(newit);
        picked_up = true;
    }

    if(picked_up) {
        Pickup::remove_from_map_or_vehicle(pickup_target,
                                           veh, cargo_part, moves_taken, index);
    }
    if( leftovers.charges > 0 ) {
        bool to_map = veh == nullptr;
        if( !to_map ) {
            to_map = !veh->add_item( cargo_part, leftovers );
        }
        if( to_map ) {
            g->m.add_item_or_charges( pickup_target, leftovers );
        }
    }
}