void activity_handlers::drop_do_turn( player_activity *act, player *p ) { const tripoint pos = act->placement + p->pos(); bool force_ground = false; for( auto &it : act->str_values ) { if( it == "force_ground" ) { force_ground = true; break; } } put_into_vehicle_or_drop( *p, item_drop_reason::deliberate, obtain_activity_items( *act, *p ), pos, force_ground ); }
static void move_item( player &p, item &it, int quantity, const tripoint &src, const tripoint &dest, vehicle *src_veh, int src_part ) { item leftovers = it; if( quantity != 0 && it.count_by_charges() ) { // Reinserting leftovers happens after item removal to avoid stacking issues. leftovers.charges = it.charges - quantity; if( leftovers.charges > 0 ) { it.charges = quantity; } } else { leftovers.charges = 0; } // Check that we can pick it up. if( !it.made_of_from_type( LIQUID ) ) { p.mod_moves( -move_cost( it, src, dest ) ); put_into_vehicle_or_drop( p, item_drop_reason::deliberate, { it }, dest ); // Remove from map or vehicle. if( src_veh ) { src_veh->remove_item( src_part, &it ); } else { g->m.i_rem( src, &it ); } } // If we didn't pick up a whole stack, put the remainder back where it came from. if( leftovers.charges > 0 ) { if( src_veh ) { if( !src_veh->add_item( src_part, leftovers ) ) { debugmsg( "SortLoot: Source vehicle failed to receive leftover charges." ); } } else { g->m.add_item_or_charges( src, leftovers ); } } }
// I'd love to have this not duplicate so much code from Pickup::pick_one_up(), // but I don't see a clean way to do that. static void move_items( player &p, const tripoint &src, bool from_vehicle, const tripoint &dest, bool to_vehicle, std::list<int> &indices, std::list<int> &quantities ) { tripoint source = src + p.pos(); tripoint destination = dest + p.pos(); int s_cargo = -1; vehicle *s_veh = nullptr; // load vehicle information if requested if( from_vehicle ) { const cata::optional<vpart_reference> vp = g->m.veh_at( source ).part_with_feature( "CARGO", false ); assert( vp ); s_veh = &vp->vehicle(); s_cargo = vp->part_index(); assert( s_cargo >= 0 ); } while( p.moves > 0 && !indices.empty() ) { int index = indices.back(); int quantity = quantities.back(); indices.pop_back(); quantities.pop_back(); item *temp_item = from_vehicle ? g->m.item_from( s_veh, s_cargo, index ) : g->m.item_from( source, index ); if( temp_item == nullptr ) { continue; // No such item. } item leftovers = *temp_item; if( quantity != 0 && temp_item->count_by_charges() ) { // Reinserting leftovers happens after item removal to avoid stacking issues. leftovers.charges = temp_item->charges - quantity; if( leftovers.charges > 0 ) { temp_item->charges = quantity; } } else { leftovers.charges = 0; } // Check that we can pick it up. if( !temp_item->made_of_from_type( LIQUID ) ) { // This is for hauling across zlevels, remove when going up and down stairs // is no longer teleportation int distance = src.z == dest.z ? std::max( rl_dist( src, dest ), 1 ) : 1; p.mod_moves( -Pickup::cost_to_move_item( p, *temp_item ) * distance ); if( to_vehicle ) { put_into_vehicle_or_drop( p, item_drop_reason::deliberate, { *temp_item }, destination ); } else { drop_on_map( p, item_drop_reason::deliberate, { *temp_item }, destination ); } // Remove from map or vehicle. if( from_vehicle ) { s_veh->remove_item( s_cargo, index ); } else { g->m.i_rem( source, index ); } } // If we didn't pick up a whole stack, put the remainder back where it came from. if( leftovers.charges > 0 ) { bool to_map = !from_vehicle; if( !to_map ) { to_map = !s_veh->add_item( s_cargo, leftovers ); } if( to_map ) { g->m.add_item_or_charges( source, leftovers ); } } } }
void put_into_vehicle_or_drop( Character &c, item_drop_reason reason, const std::list<item> &items ) { return put_into_vehicle_or_drop( c, reason, items, c.pos() ); }
// I'd love to have this not duplicate so much code from Pickup::pick_one_up(), // but I don't see a clean way to do that. static void move_items( const tripoint &src, bool from_vehicle, const tripoint &dest, bool to_vehicle, std::list<int> &indices, std::list<int> &quantities ) { tripoint source = src + g->u.pos(); tripoint destination = dest + g->u.pos(); int s_cargo, d_cargo; // oui oui, mon frere s_cargo = d_cargo = -1; vehicle *s_veh, *d_veh; // 2diva4me s_veh = d_veh = nullptr; // load vehicle information if requested if( from_vehicle ) { const cata::optional<vpart_reference> vp = g->m.veh_at( source ).part_with_feature( "CARGO", false ); assert( vp ); s_veh = &vp->vehicle(); s_cargo = vp->part_index(); assert( s_cargo >= 0 ); } if( to_vehicle ) { const cata::optional<vpart_reference> vp = g->m.veh_at( destination ).part_with_feature( "CARGO", false ); assert( vp ); d_veh = &vp->vehicle(); d_cargo = vp->part_index(); assert( d_cargo >= 0 ); } while( g->u.moves > 0 && !indices.empty() ) { int index = indices.back(); int quantity = quantities.back(); indices.pop_back(); quantities.pop_back(); item *temp_item = from_vehicle ? g->m.item_from( s_veh, s_cargo, index ) : g->m.item_from( source, index ); if( temp_item == nullptr ) { continue; // No such item. } item leftovers = *temp_item; if( quantity != 0 && temp_item->count_by_charges() ) { // Reinserting leftovers happens after item removal to avoid stacking issues. leftovers.charges = temp_item->charges - quantity; if( leftovers.charges > 0 ) { temp_item->charges = quantity; } } else { leftovers.charges = 0; } // Check that we can pick it up. if( !temp_item->made_of( LIQUID ) ) { g->u.mod_moves( -Pickup::cost_to_move_item( g->u, *temp_item ) ); if( to_vehicle ) { put_into_vehicle_or_drop( g->u, { *temp_item }, destination ); } else { drop_on_map( g->u, { *temp_item }, destination ); } // Remove from map or vehicle. if( from_vehicle ) { s_veh->remove_item( s_cargo, index ); } else { g->m.i_rem( source, index ); } } // If we didn't pick up a whole stack, put the remainder back where it came from. if( leftovers.charges > 0 ) { bool to_map = !from_vehicle; if( !to_map ) { to_map = !s_veh->add_item( s_cargo, leftovers ); } if( to_map ) { g->m.add_item_or_charges( source, leftovers ); } } } }
void activity_handlers::drop_do_turn( player_activity *act, player *p ) { const tripoint pos = act->placement + p->pos(); put_into_vehicle_or_drop( *p, obtain_activity_items( *act, *p ), pos ); }