const std::function<bool( const item & )> recipe::get_component_filter() const { const item result = create_result(); // Disallow crafting of non-perishables with rotten components // Make an exception for seeds // TODO: move seed extraction recipes to uncraft std::function<bool( const item & )> rotten_filter = return_true<item>; if( result.is_food() && !result.goes_bad() && !has_flag( "ALLOW_ROTTEN" ) ) { rotten_filter = []( const item & component ) { return !component.rotten(); }; } // If the result is made hot, we can allow frozen components. // EDIBLE_FROZEN components ( e.g. flour, chocolate ) are allowed as well // Otherwise forbid them std::function<bool( const item & )> frozen_filter = return_true<item>; if( result.is_food() && !hot_result() ) { frozen_filter = []( const item & component ) { return !component.has_flag( "FROZEN" ) || component.has_flag( "EDIBLE_FROZEN" ); }; } return [ rotten_filter, frozen_filter ]( const item & component ) { return is_crafting_component( component ) && rotten_filter( component ) && frozen_filter( component ); }; }
void finalize_crafted_item( item &newit, float used_age_tally, int used_age_count ) { if( newit.is_food() ) { set_item_food( newit ); } if( used_age_count > 0 && newit.goes_bad() ) { set_item_spoilage( newit, used_age_tally, used_age_count ); } }
int rate_freshness( const item &it, const item &container ) const { if( p.will_eat( it ).value() == edible_rating::ROTTEN ) { return -1; } else if( !container.type->container || !container.type->container->preserves ) { if( it.is_fresh() ) { return 1; } else if( it.is_going_bad() ) { return 3; } else if( it.goes_bad() ) { return 2; } } return 0; }
bool player::can_disassemble( const item &obj, const inventory &inv, std::string *err ) const { const auto error = [&err]( const std::string & message ) { if( err != nullptr ) { *err = message; } return false; }; const auto &r = recipe_dictionary::get_uncraft( obj.typeId() ); if( !r ) { return error( string_format( _( "You cannot disassemble this." ) ) ); } // check sufficient light if( lighting_craft_speed_multiplier( r ) == 0.0f ) { return error( _( "You can't see to craft!" ) ); } // refuse to disassemble rotten items if( obj.goes_bad() || ( obj.is_food_container() && obj.contents.front().goes_bad() ) ) { if( obj.rotten() || ( obj.is_food_container() && obj.contents.front().rotten() ) ) { return error( _( "It's rotten, I'm not taking that apart." ) ); } } if( obj.count_by_charges() && !r.has_flag( "UNCRAFT_SINGLE_CHARGE" ) ) { // Create a new item to get the default charges int qty = r.create_result().charges; if( obj.charges < qty ) { auto msg = ngettext( "You need at least %d charge of %s.", "You need at least %d charges of %s.", qty ); return error( string_format( msg, qty, obj.tname().c_str() ) ); } } const auto &dis = r.disassembly_requirements(); for( const auto &opts : dis.get_qualities() ) { for( const auto &qual : opts ) { if( !qual.has( inv ) ) { // Here should be no dot at the end of the string as 'to_string()' provides it. return error( string_format( _( "You need %s" ), qual.to_string().c_str() ) ); } } } for( const auto &opts : dis.get_tools() ) { const bool found = std::any_of( opts.begin(), opts.end(), [&]( const tool_comp & tool ) { return ( tool.count <= 0 && inv.has_tools( tool.type, 1 ) ) || ( tool.count > 0 && inv.has_charges( tool.type, tool.count ) ); } ); if( !found ) { if( opts.front().count <= 0 ) { return error( string_format( _( "You need %s." ), item::nname( opts.front().type ).c_str() ) ); } else { return error( string_format( ngettext( "You need a %s with %d charge.", "You need a %s with %d charges.", opts.front().count ), item::nname( opts.front().type ).c_str(), opts.front().count ) ); } } } return true; }