std::list<item> obtain_activity_items( player_activity &act, player &p ) { std::list<item> res; auto items = reorder_for_dropping( p, convert_to_indexes( act ) ); debug_drop_list( items ); while( !items.empty() && ( p.is_npc() || p.moves > 0 || items.front().consumed_moves == 0 ) ) { const auto &ait = items.front(); p.mod_moves( -ait.consumed_moves ); if( p.is_worn( *ait.it ) ) { p.takeoff( *ait.it, &res ); } else if( ait.it->count_by_charges() ) { res.push_back( p.reduce_charges( const_cast<item *>( ait.it ), ait.count ) ); } else { res.push_back( p.i_rem( ait.it ) ); } items.pop_front(); } // Avoid tumbling to the ground. Unload cleanly. const units::volume excessive_volume = p.volume_carried() - p.volume_capacity(); if( excessive_volume > 0_ml ) { const auto excess = p.inv.remove_randomly_by_volume( excessive_volume ); res.insert( res.begin(), excess.begin(), excess.end() ); } // Load anything that remains (if any) into the activity act.values.clear(); if( !items.empty() ) { for( const auto &drop : convert_to_indexes( p, items ) ) { act.values.push_back( drop.first ); act.values.push_back( drop.second ); } } // And cancel if its empty. If its not, we modified in place and we will continue // to resolve the drop next turn. This is different from the pickup logic which // creates a brand new activity every turn and cancels the old activity if( act.values.empty() ) { p.cancel_activity(); } return res; }
std::list<item> obtain_activity_items( player_activity &act, player &p ) { std::list<item> res; auto items = reorder_for_dropping( p, convert_to_indexes( act ) ); debug_drop_list( items ); while( !items.empty() && ( p.is_npc() || p.moves > 0 || items.front().consumed_moves == 0 ) ) { const auto &ait = items.front(); p.mod_moves( -ait.consumed_moves ); if( p.is_worn( *ait.it ) ) { p.takeoff( *ait.it, &res ); } else if( ait.it->count_by_charges() ) { res.push_back( p.reduce_charges( const_cast<item *>( ait.it ), ait.count ) ); } else { res.push_back( p.i_rem( ait.it ) ); } items.pop_front(); } // Avoid tumbling to the ground. Unload cleanly. const units::volume excessive_volume = p.volume_carried() - p.volume_capacity(); if( excessive_volume > 0 ) { const auto excess = p.inv.remove_randomly_by_volume( excessive_volume ); res.insert( res.begin(), excess.begin(), excess.end() ); } // Load anything that remains (if any) into the activity act.values.clear(); if( !items.empty() ) { for( const auto &drop : convert_to_indexes( p, items ) ) { act.values.push_back( drop.first ); act.values.push_back( drop.second ); } } // And either cancel if it's empty, or restart if it's not. if( act.values.empty() ) { p.cancel_activity(); } else { p.assign_activity( act ); } return res; }
void activity_handlers::washing_finish( player_activity *act, player *p ) { auto items = reorder_for_dropping( *p, convert_to_indexes( *act ) ); // Check again that we have enough water and soap incase the amount in our inventory changed somehow // Consume the water and soap units::volume total_volume = 0_ml; for( const act_item &filthy_item : items ) { total_volume += filthy_item.it->volume(); } washing_requirements required = washing_requirements_for_volume( total_volume ); const auto is_liquid_crafting_component = []( const item & it ) { return is_crafting_component( it ) && ( !it.count_by_charges() || it.made_of( LIQUID ) || it.contents_made_of( LIQUID ) ); }; const inventory &crafting_inv = p->crafting_inventory(); if( !crafting_inv.has_charges( "water", required.water, is_liquid_crafting_component ) && !crafting_inv.has_charges( "water_clean", required.water, is_liquid_crafting_component ) ) { p->add_msg_if_player( _( "You need %1$i charges of water or clean water to wash these items." ), required.water ); act->set_to_null(); return; } else if( !crafting_inv.has_charges( "soap", required.cleanser ) && !crafting_inv.has_charges( "detergent", required.cleanser ) ) { p->add_msg_if_player( _( "You need %1$i charges of cleansing agent to wash these items." ), required.cleanser ); act->set_to_null(); return; } for( const auto &ait : items ) { item *filthy_item = const_cast<item *>( ait.it ); filthy_item->item_tags.erase( "FILTHY" ); p->on_worn_item_washed( *filthy_item ); } std::vector<item_comp> comps; comps.push_back( item_comp( "water", required.water ) ); comps.push_back( item_comp( "water_clean", required.water ) ); p->consume_items( comps, 1, is_liquid_crafting_component ); std::vector<item_comp> comps1; comps1.push_back( item_comp( "soap", required.cleanser ) ); comps1.push_back( item_comp( "detergent", required.cleanser ) ); p->consume_items( comps1 ); p->add_msg_if_player( m_good, _( "You washed your clothing." ) ); // Make sure newly washed components show up as available if player attempts to craft immediately p->invalidate_crafting_inventory(); act->set_to_null(); }
void activity_handlers::washing_finish( player_activity *act, player *p ) { auto items = reorder_for_dropping( *p, convert_to_indexes( *act ) ); // Check again that we have enough water and soap incase the amount in our inventory changed somehow // Consume the water and soap int required_water = 0; int required_cleanser = 0; for( const act_item &filthy_item : items ) { required_water += filthy_item.it->volume() / 125_ml; required_cleanser += filthy_item.it->volume() / 1000_ml; } if( required_cleanser < 1 ) { required_cleanser = 1; } const inventory &crafting_inv = p->crafting_inventory(); if( !crafting_inv.has_charges( "water", required_water ) && !crafting_inv.has_charges( "water_clean", required_water ) ) { p->add_msg_if_player( _( "You need %1$i charges of water or clean water to wash these items." ), required_water ); act->set_to_null(); return; } else if( !crafting_inv.has_charges( "soap", required_cleanser ) && !crafting_inv.has_charges( "detergent", required_cleanser ) ) { p->add_msg_if_player( _( "You need %1$i charges of cleansing agent to wash these items." ), required_cleanser ); act->set_to_null(); return; } for( const auto &ait : items ) { item *filthy_item = const_cast<item *>( ait.it ); filthy_item->item_tags.erase( "FILTHY" ); } std::vector<item_comp> comps; comps.push_back( item_comp( "water", required_water ) ); comps.push_back( item_comp( "water_clean", required_water ) ); p->consume_items( comps ); std::vector<item_comp> comps1; comps1.push_back( item_comp( "soap", required_cleanser ) ); comps1.push_back( item_comp( "detergent", required_cleanser ) ); p->consume_items( comps1 ); p->add_msg_if_player( m_good, _( "You washed your clothing." ) ); act->set_to_null(); }