ret_val<edible_rating> player::will_eat( const item &food, bool interactive ) const { const auto ret = can_eat( food ); if( !ret.success() ) { if( interactive ) { add_msg_if_player( m_info, "%s", ret.c_str() ); } return ret; } std::vector<ret_val<edible_rating>> consequences; const auto add_consequence = [&consequences]( const std::string & msg, edible_rating code ) { consequences.emplace_back( ret_val<edible_rating>::make_failure( code, msg ) ); }; const bool saprophage = has_trait( trait_id( "SAPROPHAGE" ) ); const auto &comest = food.type->comestible; if( food.rotten() ) { const bool saprovore = has_trait( trait_id( "SAPROVORE" ) ); if( !saprophage && !saprovore ) { add_consequence( _( "This is rotten and smells awful!" ), ROTTEN ); } } const bool carnivore = has_trait( trait_id( "CARNIVORE" ) ); if( food.has_flag( "CANNIBALISM" ) && !has_trait_flag( "CANNIBAL" ) ) { add_consequence( _( "The thought of eating human flesh makes you feel sick." ), CANNIBALISM ); } const bool edible = comest->comesttype == "FOOD" || food.has_flag( "USE_EAT_VERB" ); if( edible && has_effect( effect_nausea ) ) { add_consequence( _( "You still feel nauseous and will probably puke it all up again." ), NAUSEA ); } if( ( allergy_type( food ) != MORALE_NULL ) || ( carnivore && food.has_flag( "ALLERGEN_JUNK" ) && !food.has_flag( "CARNIVORE_OK" ) ) ) { add_consequence( _( "Your stomach won't be happy (allergy)." ), ALLERGY ); } if( saprophage && edible && food.rotten() && !food.has_flag( "FERTILIZER" ) ) { // Note: We're allowing all non-solid "food". This includes drugs // Hard-coding fertilizer for now - should be a separate flag later //~ No, we don't eat "rotten" food. We eat properly aged food, like a normal person. //~ Semantic difference, but greatly facilitates people being proud of their character. add_consequence( _( "Your stomach won't be happy (not rotten enough)." ), ALLERGY_WEAK ); } const int nutr = nutrition_for( food ); const int quench = comest->quench; const int temp_hunger = get_hunger() - nutr; const int temp_thirst = get_thirst() - quench; if( !has_active_mutation( trait_id( "EATHEALTH" ) ) && !has_active_mutation( trait_id( "HIBERNATE" ) ) && !has_trait( trait_id( "SLIMESPAWNER" ) ) ) { if( get_hunger() < 0 && nutr >= 5 && !has_active_mutation( trait_id( "GOURMAND" ) ) ) { add_consequence( _( "You're full already and will be forcing yourself to eat." ), TOO_FULL ); } else if( ( ( nutr > 0 && temp_hunger < stomach_capacity() ) || ( comest->quench > 0 && temp_thirst < stomach_capacity() ) ) && !food.has_infinite_charges() ) { add_consequence( _( "You will not be able to finish it all." ), TOO_FULL ); } } if( !consequences.empty() ) { if( !interactive ) { return consequences.front(); } std::ostringstream req; for( const auto &elem : consequences ) { req << elem.str() << std::endl; } const bool eat_verb = food.has_flag( "USE_EAT_VERB" ); if( eat_verb || comest->comesttype == "FOOD" ) { req << string_format( _( "Eat your %s anyway?" ), food.tname().c_str() ); } else if( !eat_verb && comest->comesttype == "DRINK" ) { req << string_format( _( "Drink your %s anyway?" ), food.tname().c_str() ); } else { req << string_format( _( "Consume your %s anyway?" ), food.tname().c_str() ); } if( !query_yn( req.str() ) ) { return consequences.front(); } } // All checks ended, it's edible (or we're pretending it is) return ret_val<edible_rating>::make_success(); }