diff --git a/data/json/mutations/mutations.json b/data/json/mutations/mutations.json index 544b8d198db89..092e661c7cca2 100644 --- a/data/json/mutations/mutations.json +++ b/data/json/mutations/mutations.json @@ -3279,13 +3279,32 @@ "id": "EATHEALTH", "name": { "str": "Hyper-Metabolism" }, "points": 15, - "description": "You metabolize nutrients so rapidly that you can convert food directly into useful tissue. Excess nutrition will convert to HP, rather than being wasted. Activate to skip prompt for overeating.", + "description": "Your particular metabolism allows you to burn calories at a prodigious rate to regenerate tissues in a matter of minutes, this is however a very wasteful process. Activate to start healing.", "prereqs": [ "HUNGER3" ], "types": [ "METABOLISM" ], "threshreq": [ "THRESH_CHIMERA" ], "category": [ "CHIMERA" ], "valid": false, - "active": true + "active": true, + "transform": { + "target": "EATHEALTH_active", + "msg_transform": "Your hyper-metabolism starts burning up calories.", + "active": true, + "moves": 0 + } + }, + { + "type": "mutation", + "id": "EATHEALTH_active", + "name": { "str": "Hyper-Metabolism: burning" }, + "description": "You're burning calories like crazy to heal your wounds.", + "copy-from": "EATHEALTH", + "cost": 1, + "time": 1, + "hunger": true, + "healing_awake": 300.0, + "healing_resting": 350.0, + "transform": { "target": "EATHEALTH", "msg_transform": "Your hyper-metabolism slows down.", "active": false, "moves": 0 } }, { "type": "mutation", diff --git a/src/character.h b/src/character.h index 12c5313497681..bb0e9ec7b88fb 100644 --- a/src/character.h +++ b/src/character.h @@ -471,8 +471,7 @@ class Character : public Creature, public visitable virtual int get_hunger() const; virtual int get_starvation() const; virtual int get_thirst() const; - /** Gets character's minimum hunger and thirst */ - int stomach_capacity() const; + std::pair get_thirst_description() const; std::pair get_hunger_description() const; std::pair get_fatigue_description() const; @@ -1152,6 +1151,11 @@ class Character : public Creature, public visitable void mutation_loss_effect( const trait_id &mut ); bool has_active_mutation( const trait_id &b ) const; + + int get_cost_timer( const trait_id &mut_id ) const; + void set_cost_timer( const trait_id &mut, int set ); + void mod_cost_timer( const trait_id &mut, int mod ); + /** Picks a random valid mutation and gives it to the Character, possibly removing/changing others along the way */ void mutate(); /** Returns true if the player doesn't have the mutation or a conflicting one and it complies with the force typing */ @@ -2754,8 +2758,8 @@ class Character : public Creature, public visitable std::map bodypart_exposure(); private: /** suffer() subcalls */ - void suffer_water_damage( const mutation_branch &mdata ); - void suffer_mutation_power( const mutation_branch &mdata, Character::trait_data &tdata ); + void suffer_water_damage( const trait_id &mut_id ); + void suffer_mutation_power( const trait_id &mut_id ); void suffer_while_underwater(); void suffer_from_addictions(); void suffer_while_awake( int current_stim ); diff --git a/src/consumption.cpp b/src/consumption.cpp index f9e6d66a14fae..cf38cfec4da6e 100644 --- a/src/consumption.cpp +++ b/src/consumption.cpp @@ -143,23 +143,6 @@ static const std::map plut_charges = { { itype_id( "plut_slurry" ), PLUTONIUM_CHARGES / 2 } }; -int Character::stomach_capacity() const -{ - if( has_trait( trait_GIZZARD ) ) { - return 0; - } - - if( has_active_mutation( trait_HIBERNATE ) ) { - return -620; - } - - if( has_trait( trait_GOURMAND ) || has_trait( trait_HIBERNATE ) ) { - return -60; - } - - return -20; -} - // TODO: Move pizza scraping here. static int compute_default_effective_kcal( const item &comest, const Character &you, const cata::flat_set &extra_flags = {} ) @@ -1342,8 +1325,6 @@ bool Character::consume_effects( item &food ) mod_fatigue( nutr ); } } - // TODO: remove this - int capacity = stomach_capacity(); // Moved here and changed a bit - it was too complex // Incredibly minor stuff like this shouldn't require complexity if( !is_npc() && has_trait( trait_SLIMESPAWNER ) && @@ -1365,24 +1346,6 @@ bool Character::consume_effects( item &food ) add_msg_if_player( m_good, _( "hey, you look like me! let's work together!" ) ); } - // Last thing that happens before capping hunger - if( get_hunger() < capacity && has_trait( trait_EATHEALTH ) ) { - int excess_food = capacity - get_hunger(); - add_msg_player_or_npc( _( "You feel the %s filling you out." ), - _( " looks better after eating the %s." ), - food.tname() ); - // Guaranteed 1 HP healing, no matter what. You're welcome. ;-) - if( excess_food <= 5 ) { - healall( 1 ); - } else { - // Straight conversion, except it's divided amongst all your body parts. - healall( excess_food /= 5 ); - } - - // Note: We want this here to prevent "you can't finish this" messages - set_hunger( capacity ); - } - nutrients food_nutrients = compute_effective_nutrients( food ); const units::volume water_vol = ( food.get_comestible()->quench > 0 ) ? food.get_comestible()->quench * diff --git a/src/mutation.cpp b/src/mutation.cpp index e3fbfe8c77cd9..bfa91bd11a74c 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -499,6 +499,32 @@ bool Character::has_active_mutation( const trait_id &b ) const return iter != my_mutations.end() && iter->second.powered; } +int Character::get_cost_timer( const trait_id &mut ) const +{ + const auto iter = my_mutations.find( mut ); + if( iter != my_mutations.end() ) { + return iter->second.charge; + } else { + debugmsg( "Tried to get cost timer of %s but doesn't have this mutation.", mut.c_str() ); + } + return 0; +} + +void Character::set_cost_timer( const trait_id &mut, int set ) +{ + const auto iter = my_mutations.find( mut ); + if( iter != my_mutations.end() ) { + iter->second.charge = set; + } else { + debugmsg( "Tried to set cost timer of %s but doesn't have this mutation.", mut.c_str() ); + } +} + +void Character::mod_cost_timer( const trait_id &mut, int mod ) +{ + set_cost_timer( mut, get_cost_timer( mut ) + mod ); +} + bool Character::is_category_allowed( const std::vector &category ) const { bool allowed = false; diff --git a/src/suffer.cpp b/src/suffer.cpp index acfef068d5410..e42c831a6fa60 100644 --- a/src/suffer.cpp +++ b/src/suffer.cpp @@ -174,11 +174,11 @@ static float addiction_scaling( float at_min, float at_max, float add_lvl ) return lerp( at_min, at_max, ( add_lvl - MIN_ADDICTION_LEVEL ) / MAX_ADDICTION_LEVEL ); } -void Character::suffer_water_damage( const mutation_branch &mdata ) +void Character::suffer_water_damage( const trait_id &mut_id ) { for( const std::pair &elem : get_body() ) { const float wetness_percentage = elem.second.get_wetness_percentage(); - const int dmg = mdata.weakness_to_water * wetness_percentage; + const int dmg = mut_id->weakness_to_water * wetness_percentage; if( dmg > 0 ) { apply_damage( nullptr, elem.first, dmg ); add_msg_player_or_npc( m_bad, _( "Your %s is damaged by the water." ), @@ -193,51 +193,49 @@ void Character::suffer_water_damage( const mutation_branch &mdata ) } } -void Character::suffer_mutation_power( const mutation_branch &mdata, - Character::trait_data &tdata ) +void Character::suffer_mutation_power( const trait_id &mut_id ) { - if( tdata.powered && tdata.charge > 0 ) { - // Already-on units just lose a bit of charge - tdata.charge--; + if( get_cost_timer( mut_id ) > 0 ) { + // Not ready to consume cost yet, the timer ticks on + mod_cost_timer( mut_id, -1 ); } else { - // Not-on units, or those with zero charge, have to pay the power cost - if( mdata.cooldown > 0 ) { - tdata.powered = true; - tdata.charge = mdata.cooldown - 1; - } - if( mdata.hunger ) { - // does not directly modify hunger, but burns kcal - mod_stored_nutr( mdata.cost ); + // Ready to consume cost: pay the power cost and reset timer + if( mut_id->cooldown > 0 ) { + set_cost_timer( mut_id, mut_id->cooldown - 1 ); + } + if( mut_id->hunger ) { if( get_bmi() < character_weight_category::underweight ) { add_msg_if_player( m_warning, _( "You're too malnourished to keep your %s going." ), - mdata.name() ); - tdata.powered = false; + mut_id->name() ); + deactivate_mutation( mut_id ); + } else { + // does not directly modify hunger, but burns kcal + mod_stored_nutr( mut_id->cost ); } } - if( mdata.thirst ) { - mod_thirst( mdata.cost ); + if( mut_id->thirst ) { // Well into Dehydrated if( get_thirst() >= 260 ) { add_msg_if_player( m_warning, _( "You're too dehydrated to keep your %s going." ), - mdata.name() ); - tdata.powered = false; + mut_id->name() ); + deactivate_mutation( mut_id ); + } else { + mod_thirst( mut_id->cost ); } } - if( mdata.fatigue ) { - mod_fatigue( mdata.cost ); + if( mut_id->fatigue ) { // Exhausted if( get_fatigue() >= fatigue_levels::EXHAUSTED ) { add_msg_if_player( m_warning, _( "You're too exhausted to keep your %s going." ), - mdata.name() ); - tdata.powered = false; + mut_id->name() ); + deactivate_mutation( mut_id ); + } else { + mod_fatigue( mut_id->cost ); } } - if( !tdata.powered ) { - apply_mods( mdata.id, false ); - } } } @@ -1529,14 +1527,12 @@ void Character::suffer() process_bionic( i ); } - for( std::pair &mut : my_mutations ) { - const mutation_branch &mdata = mut.first.obj(); + for( const trait_id &mut_id : get_mutations() ) { if( calendar::once_every( 1_minutes ) ) { - suffer_water_damage( mdata ); + suffer_water_damage( mut_id ); } - Character::trait_data &tdata = mut.second; - if( tdata.powered ) { - suffer_mutation_power( mdata, tdata ); + if( has_active_mutation( mut_id ) ) { + suffer_mutation_power( mut_id ); } }