diff --git a/src/character.cpp b/src/character.cpp index ac7e319b73cea..fbd87507f619c 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -6386,6 +6386,11 @@ float Character::get_bmi_fat() const 2 ) * get_cached_organic_size() ); } +bool Character::has_calorie_deficit() const +{ + return get_bmi_fat() < character_weight_category::normal; +} + units::mass Character::bodyweight() const { return bodyweight_fat() + bodyweight_lean(); diff --git a/src/character.h b/src/character.h index a5ef82c25026c..0edbec33c336e 100644 --- a/src/character.h +++ b/src/character.h @@ -3002,6 +3002,7 @@ class Character : public Creature, public visitable float get_bmi() const; float get_bmi_fat() const; float get_bmi_lean() const; + bool has_calorie_deficit() const; // returns amount of calories burned in a day given various metabolic factors int get_bmr() const; // add spent calories to calorie diary (if avatar) diff --git a/src/character_body.cpp b/src/character_body.cpp index 0c37177aef087..e195b713f2d64 100644 --- a/src/character_body.cpp +++ b/src/character_body.cpp @@ -1048,7 +1048,7 @@ void Character::update_stomach( const time_point &from, const time_point &to ) set_thirst( 0 ); } - const bool calorie_deficit = get_bmi_fat() < character_weight_category::normal; + const bool calorie_deficit = has_calorie_deficit(); const units::volume contains = stomach.contains(); const units::volume cap = stomach.capacity( *this ); @@ -1065,9 +1065,9 @@ void Character::update_stomach( const time_point &from, const time_point &to ) // > 3/4 cap full full full // > 1/2 cap satisfied v. hungry famished/(near)starving // <= 1/2 cap hungry v. hungry famished/(near)starving - if( contains >= cap ) { + if( stomach.would_be_engorged_with( *this, 0_ml, calorie_deficit ) ) { hunger_effect = effect_hunger_engorged; - } else if( contains > cap * 3 / 4 ) { + } else if( stomach.would_be_full_with( *this, 0_ml, calorie_deficit ) ) { hunger_effect = effect_hunger_full; } else if( just_ate && contains > cap / 2 ) { hunger_effect = effect_hunger_satisfied; @@ -1090,9 +1090,9 @@ void Character::update_stomach( const time_point &from, const time_point &to ) // >= 3/8 cap satisfied satisfied blank // > 0 blank blank blank // 0 blank blank (v.) hungry - if( contains >= cap * 5 / 6 ) { + if( stomach.would_be_engorged_with( *this, 0_ml, calorie_deficit ) ) { hunger_effect = effect_hunger_engorged; - } else if( contains > cap * 11 / 20 ) { + } else if( stomach.would_be_full_with( *this, 0_ml, calorie_deficit ) ) { hunger_effect = effect_hunger_full; } else if( recently_ate && contains >= cap * 3 / 8 ) { hunger_effect = effect_hunger_satisfied; diff --git a/src/consumption.cpp b/src/consumption.cpp index 9bb8dcc0d0dd4..992f5d0c2999f 100644 --- a/src/consumption.cpp +++ b/src/consumption.cpp @@ -992,8 +992,9 @@ ret_val Character::will_eat( const item &food, bool interactive ) add_consequence( _( "Your stomach won't be happy (not rotten enough)." ), ALLERGY_WEAK ); } + units::volume in_stomach_volume = food.volume() * compute_effective_food_volume_ratio( food ); if( food.is_food() && - ( food.charges_per_volume( stomach.stomach_remaining( *this ) ) < 1 || + ( stomach.would_be_engorged_with( *this, in_stomach_volume, has_calorie_deficit() ) || has_effect( effect_hunger_full ) || has_effect( effect_hunger_engorged ) ) ) { if( edible ) { add_consequence( _( "You're full already and will be forcing yourself to eat." ), TOO_FULL ); diff --git a/src/stomach.cpp b/src/stomach.cpp index 7a41b8e8b811e..1aa611f3fc2ed 100644 --- a/src/stomach.cpp +++ b/src/stomach.cpp @@ -313,6 +313,30 @@ units::volume stomach_contents::stomach_remaining( const Character &owner ) cons return capacity( owner ) - contents - water; } +bool stomach_contents::would_be_engorged_with( const Character &owner, units::volume intake, + bool calorie_deficit ) const +{ + const double fullness_ratio = ( contains() + intake ) / capacity( owner ); + if( calorie_deficit && fullness_ratio >= 1.0 ) { + return true; + } else if( fullness_ratio >= 5.0 / 6.0 ) { + return true; + } + return false; +} + +bool stomach_contents::would_be_full_with( const Character &owner, units::volume intake, + bool calorie_deficit ) const +{ + const double fullness_ratio = ( contains() + intake ) / capacity( owner ); + if( calorie_deficit && fullness_ratio >= 11.0 / 20.0 ) { + return true; + } else if( fullness_ratio >= 3.0 / 4.0 ) { + return true; + } + return false; +} + units::volume stomach_contents::contains() const { return contents + water; diff --git a/src/stomach.h b/src/stomach.h index 62bd9c5f3732d..c7f62da3c4874 100644 --- a/src/stomach.h +++ b/src/stomach.h @@ -164,6 +164,10 @@ class stomach_contents * @return This stomach's capacity, in units::volume */ units::volume capacity( const Character &owner ) const; + // These functions need a ref to the stomach's owner because capacity() does + bool would_be_engorged_with( const Character &owner, units::volume intake, + bool calorie_deficit ) const; + bool would_be_full_with( const Character &owner, units::volume intake, bool calorie_deficit ) const; // how much stomach capacity you have left before you puke from stuffing your gob units::volume stomach_remaining( const Character &owner ) const; // how much volume is in the stomach_contents