int obtain( Character& ch ) override { if( !what ) { return INT_MIN; } // invalidate this item_location auto it = get_item(); what = nullptr; int mv = 0; bool was_worn = false; item *holster = who->find_parent( *it ); if( holster && who->is_worn( *holster ) && holster->can_holster( *it, true ) ) { // Immediate parent is a worn holster capable of holding this item auto ptr = dynamic_cast<const holster_actor *>( holster->type->get_use( "holster" )->get_actor_ptr() ); mv += dynamic_cast<player *>( who )->item_handling_cost( *it, false, ptr->draw_cost ); was_worn = true; } else { // Unpack the object followed by any nested containers starting with the innermost mv += dynamic_cast<player *>( who )->item_handling_cost( *it ); for( auto obj = who->find_parent( *it ); obj && who->find_parent( *obj ); obj = who->find_parent( *obj ) ) { mv += dynamic_cast<player *>( who )->item_handling_cost( *obj ); } } if( who->is_worn( *it ) ) { it->on_takeoff( *( dynamic_cast<player *>( who ) ) ); } else if( !was_worn ) { mv *= INVENTORY_HANDLING_FACTOR; } if( &ch != who ) { // @todo implement movement cost for transfering item between characters } who->moves -= mv; if( &ch.i_at( ch.get_item_position( it ) ) == it ) { // item already in target characters inventory at base of stack return ch.get_item_position( it ); } else { return ch.get_item_position( &ch.i_add( who->i_rem( it ) ) ); } }
std::list<item> visitable<Character>::remove_items_with( const std::function<bool( const item &e )> &filter, int count ) { auto ch = static_cast<Character *>( this ); std::list<item> res; if( count <= 0 ) { return res; // nothing to do } // first try and remove items from the inventory res = ch->inv.remove_items_with( filter, count ); count -= res.size(); if( count == 0 ) { return res; } // then try any worn items for( auto iter = ch->worn.begin(); iter != ch->worn.end(); ) { if( filter( *iter ) ) { iter->on_takeoff( *ch ); res.splice( res.end(), ch->worn, iter++ ); if( --count == 0 ) { return res; } } else { remove_internal( filter, *iter, count, res ); if( count == 0 ) { return res; } ++iter; } } // finally try the currently wielded item (if any) if( filter( ch->weapon ) ) { res.push_back( ch->remove_weapon() ); count--; } else { remove_internal( filter, ch->weapon, count, res ); } return res; }