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!" ) ); } }
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!")); } }
//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; }
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 ); } } }