diff --git a/data/json/bionics.json b/data/json/bionics.json index b8ab0e02e72c7..39eff69fbf13e 100644 --- a/data/json/bionics.json +++ b/data/json/bionics.json @@ -753,6 +753,7 @@ "occupied_bodyparts": [ [ "torso", 20 ] ], "vitamin_absorb_mod": 1.5, "flags": [ "BIONIC_NPC_USABLE", "BIONIC_SHOCKPROOF", "PARAIMMUNE", "IMMUNE_SPOIL" ], + "enchantments": [ { "values": [ { "value": "KCAL", "multiply": 0.5 } ] } ], "cant_remove_reason": "The CBM has replaced the patient's digestive organs and cannot be removed.", "canceled_mutations": [ "WEAKSTOMACH", diff --git a/data/json/mutations/mutations.json b/data/json/mutations/mutations.json index 199af9ac7ad5d..04dbfc163f55a 100644 --- a/data/json/mutations/mutations.json +++ b/data/json/mutations/mutations.json @@ -4595,6 +4595,7 @@ "description": "You seem to get full faster now, and food goes through you more rapidly as well.", "purifiable": false, "stomach_size_multiplier": 0.9, + "enchantments": [ { "values": [ { "value": "KCAL", "multiply": -0.4 } ] } ], "prereqs": [ "BEAK", "BEAK_PECK", "BEAK_HUM" ], "prereqs2": [ "LIGHTEATER" ], "threshreq": [ "THRESH_BIRD" ], diff --git a/data/mods/Aftershock/player/bionics.json b/data/mods/Aftershock/player/bionics.json index d36e1f4c28623..170c270ec544e 100644 --- a/data/mods/Aftershock/player/bionics.json +++ b/data/mods/Aftershock/player/bionics.json @@ -57,6 +57,7 @@ "type": "bionic", "name": { "str": "Linguistic Coprocessor" }, "description": "The left hemisphere of your brain has been augmented with a microcomputer that moderately increases the speed that language and written words are processed, granting a 15% increase to reading speed.", + "enchantments": [ { "condition": "ALWAYS", "values": [ { "value": "READING_SPEED_MULTIPLIER", "multiply": -0.15 } ] } ], "occupied_bodyparts": [ [ "head", 2 ] ] }, { diff --git a/doc/MAGIC.md b/doc/MAGIC.md index cda4808009b61..a5086ff4cd061 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -865,6 +865,18 @@ Character status value | Description `REGEN_STAMINA` | `THIRST` | `WEAPON_DISPERSION` | Positive value increase the dispersion, negative decrease one. +`OVERMAP_SIGHT` | Increases the amount of overmap tiles you can see around. +`STEALTH_MODIFIER` | Same as mutation `stealth_modifier` value, amount to be subtracted from player's visibility range, capped to 60. Negative values work, but are not very effective due to the way vision ranges are capped. +`MENDING_MODIFIER` | Changes the speed of your limb mend. Since it's a percent, using `multiply` is recommended. +`KCAL` | Same as bio_digestion effect, increases the amount of calories obrained from the food. +`VITAMIN_ABSORB_MOD` | Increases amount of vitamins obtained from the food +`READING_SPEED_MULTIPLIER` | Changes how fast you can read books; Lesser value means faster book reading, with cap of 1 second. +`MELEE_STAMINA_CONSUMPTION` | Changes amount of stamina used when swing in melee; stamina consumption is a negative value, so `"add": 100` decreases amount of stamina consumed, when `"add": -100` increases it; `"multiply": 1` increases, `"multiply": -0.5` decreases it. Can't be bigger than -50. +`OBTAIN_COST_MULTIPLIER` | same as `obtain_cost_multiplier`, modifier for pulling an item from a container and storing it back, as a handling penalty. `"add": 100` add 100 additional moves to item wield (1 second) +`STOMACH_SIZE_MULTIPLIER` | Same as mutation `stomach_size_multiplier` field, changes how much food you can consume at once. `"add": 1000` adds 1 L to stomach size +`CASTING_TIME_MULTIPLIER` | Same as mutation `casting_time_multiplier` field, changes your casting speed. Since it's a percent, using `multiply` is recommended. `"multiply": 2"` triples the casting speed +`CRAFTING_SPEED_MULTIPLIER` | Same as mutation `crafting_speed_multiplier` field, changes your crafting speed. Since it's a percent, using `multiply` is recommended. +`BIONIC_MANA_PENALTY` | same as mutation `bionic_mana_penalty` field, changes how big the mana penalty for having bionic energy is (default ratio is 1 kj removes 1 mana point). better to use with `multiply`, using `add` just adds or removes flat amount of mana no matter of energy level. `"multiply": 1` double the ratio (1 kj removes 2 mana points), `"multiply": -0.5` halves it Melee-only enchantment values | Description diff --git a/src/character.cpp b/src/character.cpp index fbe5fb912fa7c..a5f288f5b12c4 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -147,7 +147,6 @@ static const ammotype ammo_battery( "battery" ); static const anatomy_id anatomy_human_anatomy( "human_anatomy" ); -static const bionic_id afs_bio_linguistic_coprocessor( "afs_bio_linguistic_coprocessor" ); static const bionic_id bio_gills( "bio_gills" ); static const bionic_id bio_ground_sonar( "bio_ground_sonar" ); static const bionic_id bio_hydraulics( "bio_hydraulics" ); @@ -1304,6 +1303,8 @@ int Character::overmap_sight_range( float light_level ) const // Mutations like Scout and Topographagnosia affect how far you can see. sight += mutation_value( "overmap_sight" ); + sight = enchantment_cache->modify_value( enchant_vals::mod::OVERMAP_SIGHT, sight ); + float multiplier = mutation_value( "overmap_multiplier" ); // If sight is change due to overmap_sight, process the rest of the modifiers, otherwise skip them if( sight > 0 ) { @@ -3517,12 +3518,9 @@ int Character::read_speed() const /** @EFFECT_INT affects reading speed by an decreasing amount the higher intelligence goes, intially about 9% per point at 4 int to lower than 4% at 20+ int */ time_duration ret = 180_seconds / intel; - if( has_bionic( afs_bio_linguistic_coprocessor ) ) { // Aftershock - ret *= .85; - } - ret *= mutation_value( "reading_speed_multiplier" ); + ret = enchantment_cache->modify_value( enchant_vals::mod::READING_SPEED_MULTIPLIER, ret ); if( ret < 1_seconds ) { ret = 1_seconds; } @@ -6044,6 +6042,8 @@ int Character::visibility( bool, int ) const // TODO: // if ( dark_clothing() && light check ... int stealth_modifier = std::floor( mutation_value( "stealth_modifier" ) ); + stealth_modifier = enchantment_cache->modify_value( enchant_vals::mod::STEALTH_MODIFIER, + stealth_modifier ); return clamp( 100 - stealth_modifier, 40, 160 ); } diff --git a/src/consumption.cpp b/src/consumption.cpp index 75576fb16a2b2..06c5f2f0b28f4 100644 --- a/src/consumption.cpp +++ b/src/consumption.cpp @@ -57,7 +57,6 @@ static const std::string comesttype_DRINK( "DRINK" ); static const std::string comesttype_FOOD( "FOOD" ); -static const bionic_id bio_digestion( "bio_digestion" ); static const bionic_id bio_faulty_grossfood( "bio_faulty_grossfood" ); static const bionic_id bio_syringe( "bio_syringe" ); static const bionic_id bio_taste_blocker( "bio_taste_blocker" ); @@ -131,7 +130,6 @@ static const trait_id trait_ANTIWHEAT( "ANTIWHEAT" ); static const trait_id trait_CARNIVORE( "CARNIVORE" ); static const trait_id trait_EATDEAD( "EATDEAD" ); static const trait_id trait_EATHEALTH( "EATHEALTH" ); -static const trait_id trait_GIZZARD( "GIZZARD" ); static const trait_id trait_GOURMAND( "GOURMAND" ); static const trait_id trait_HERBIVORE( "HERBIVORE" ); static const trait_id trait_HIBERNATE( "HIBERNATE" ); @@ -194,10 +192,6 @@ static int compute_default_effective_kcal( const item &comest, const Character & kcal *= 0.75f; } - if( you.has_trait( trait_GIZZARD ) ) { - kcal *= 0.6f; - } - if( you.has_trait( trait_CARNIVORE ) && comest.has_flag( flag_CARNIVORE_OK ) && comest.has_any_flag( carnivore_blacklist ) ) { // TODO: Comment pizza scrapping @@ -213,10 +207,7 @@ static int compute_default_effective_kcal( const item &comest, const Character & kcal *= ( 1.0f - rottedness ); } - // Bionic digestion gives extra nutrition - if( you.has_bionic( bio_digestion ) ) { - kcal *= 1.5f; - } + kcal = you.enchantment_cache->modify_value( enchant_vals::mod::KCAL, kcal ); return static_cast( kcal ); } @@ -265,6 +256,10 @@ static std::map compute_default_effective_vitamins( vit.second *= bid->vitamin_absorb_mod; } } + for( std::pair &vit : res ) { + vit.second = you.enchantment_cache->modify_value( enchant_vals::mod::VITAMIN_ABSORB_MOD, + vit.second ); + } return res; } diff --git a/src/crafting.cpp b/src/crafting.cpp index 0fc9b7161b487..6f0d03cd3daa5 100644 --- a/src/crafting.cpp +++ b/src/crafting.cpp @@ -281,9 +281,13 @@ float Character::workbench_crafting_speed_multiplier( const item &craft, float Character::crafting_speed_multiplier( const recipe &rec ) const { - const float result = morale_crafting_speed_multiplier( rec ) * - lighting_craft_speed_multiplier( rec ) * - get_limb_score( limb_score_manip ); + float crafting_speed = morale_crafting_speed_multiplier( rec ) * + lighting_craft_speed_multiplier( rec ) * + get_limb_score( limb_score_manip ); + + const float result = enchantment_cache->modify_value( enchant_vals::mod::CRAFTING_SPEED_MULTIPLIER, + crafting_speed ); + add_msg_debug( debugmode::DF_CHARACTER, "Limb score multiplier %.1f, crafting speed multiplier %1f", get_limb_score( limb_score_manip ), result ); diff --git a/src/item_location.cpp b/src/item_location.cpp index 44e84f46ecb93..68dcea43eefe8 100644 --- a/src/item_location.cpp +++ b/src/item_location.cpp @@ -719,6 +719,8 @@ class item_location::impl::item_in_container : public item_location::impl int primary_cost = ch.mutation_value( "obtain_cost_multiplier" ) * ch.item_handling_cost( *target(), true, container_mv ); + primary_cost = ch.enchantment_cache->modify_value( enchant_vals::mod::OBTAIN_COST_MULTIPLIER, + primary_cost ); int parent_obtain_cost = container.obtain_cost( ch, qty ); if( container->get_use( "holster" ) ) { if( ch.is_worn( *container ) ) { diff --git a/src/magic.cpp b/src/magic.cpp index b2e59c9371289..42d0b1559eebc 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -1177,6 +1177,9 @@ int spell::casting_time( const Character &guy, bool ignore_encumb ) const casting_time *= guy.mutation_value( "casting_time_multiplier" ); + casting_time = guy.enchantment_cache->modify_value( enchant_vals::mod::CASTING_TIME_MULTIPLIER, + casting_time ); + if( !ignore_encumb && temp_somatic_difficulty_multiplyer > 0 ) { if( !has_flag( spell_flag::NO_LEGS ) ) { // the first 20 points of encumbrance combined is ignored @@ -2151,9 +2154,13 @@ void known_magic::mod_mana( const Character &guy, int add_mana ) int known_magic::max_mana( const Character &guy ) const { const float int_bonus = ( ( 0.2f + guy.get_int() * 0.1f ) - 1.0f ) * mana_base; - const int bionic_penalty = std::round( std::max( 0.0f, - units::to_kilojoule( guy.get_power_level() ) * - guy.mutation_value( "bionic_mana_penalty" ) ) ); + int penalty_calc = std::round( std::max( 0.0f, + units::to_kilojoule( guy.get_power_level() ) * + guy.mutation_value( "bionic_mana_penalty" ) ) ); + + const int bionic_penalty = guy.enchantment_cache->modify_value( + enchant_vals::mod::BIONIC_MANA_PENALTY, penalty_calc ); + const float unaugmented_mana = std::max( 0.0f, ( ( mana_base + int_bonus ) * guy.mutation_value( "mana_multiplier" ) ) + guy.mutation_value( "mana_modifier" ) - bionic_penalty ); diff --git a/src/magic_enchantment.cpp b/src/magic_enchantment.cpp index 2d557a8fc1d93..da36280f839f9 100644 --- a/src/magic_enchantment.cpp +++ b/src/magic_enchantment.cpp @@ -99,6 +99,18 @@ namespace io case enchant_vals::mod::MOD_HEALTH_CAP: return "MOD_HEALTH_CAP"; case enchant_vals::mod::READING_EXP: return "READING_EXP"; case enchant_vals::mod::SKILL_RUST_RESIST: return "SKILL_RUST_RESIST"; + case enchant_vals::mod::OVERMAP_SIGHT: return "OVERMAP_SIGHT"; + case enchant_vals::mod::READING_SPEED_MULTIPLIER: return "READING_SPEED_MULTIPLIER"; + case enchant_vals::mod::KCAL: return "KCAL"; + case enchant_vals::mod::VITAMIN_ABSORB_MOD: return "VITAMIN_ABSORB_MOD"; + case enchant_vals::mod::MELEE_STAMINA_CONSUMPTION: return "MELEE_STAMINA_CONSUMPTION"; + case enchant_vals::mod::OBTAIN_COST_MULTIPLIER: return "OBTAIN_COST_MULTIPLIER"; + case enchant_vals::mod::CASTING_TIME_MULTIPLIER: return "CASTING_TIME_MULTIPLIER"; + case enchant_vals::mod::CRAFTING_SPEED_MULTIPLIER: return "CRAFTING_SPEED_MULTIPLIER"; + case enchant_vals::mod::BIONIC_MANA_PENALTY: return "BIONIC_MANA_PENALTY"; + case enchant_vals::mod::STEALTH_MODIFIER: return "STEALTH_MODIFIER"; + case enchant_vals::mod::MENDING_MODIFIER: return "MENDING_MODIFIER"; + case enchant_vals::mod::STOMACH_SIZE_MULTIPLIER: return "STOMACH_SIZE_MULTIPLIER"; case enchant_vals::mod::LEARNING_FOCUS: return "LEARNING_FOCUS"; case enchant_vals::mod::RECOIL_MODIFIER: return "RECOIL_MODIFIER"; case enchant_vals::mod::ARMOR_ACID: return "ARMOR_ACID"; @@ -844,6 +856,22 @@ units::mass enchant_cache::modify_value( const enchant_vals::mod mod_val, return value; } +units::volume enchant_cache::modify_value( const enchant_vals::mod mod_val, + units::volume value ) const +{ + value += units::from_milliliter( get_value_add( mod_val ) ); + value *= 1.0 + get_value_multiply( mod_val ); + return value; +} + +time_duration enchant_cache::modify_value( const enchant_vals::mod mod_val, + time_duration value ) const +{ + value += time_duration::from_seconds( get_value_add( mod_val ) ); + value *= 1.0 + get_value_multiply( mod_val ); + return value; +} + int enchant_cache::mult_bonus( enchant_vals::mod value_type, int base_value ) const { return get_value_multiply( value_type ) * base_value; diff --git a/src/magic_enchantment.h b/src/magic_enchantment.h index 72266f07cade5..ce1e60424e04a 100644 --- a/src/magic_enchantment.h +++ b/src/magic_enchantment.h @@ -76,6 +76,18 @@ enum class mod : int { MOD_HEALTH_CAP, READING_EXP, SKILL_RUST_RESIST, + READING_SPEED_MULTIPLIER, + OVERMAP_SIGHT, + KCAL, + VITAMIN_ABSORB_MOD, + MELEE_STAMINA_CONSUMPTION, + OBTAIN_COST_MULTIPLIER, + CASTING_TIME_MULTIPLIER, + CRAFTING_SPEED_MULTIPLIER, + BIONIC_MANA_PENALTY, + STEALTH_MODIFIER, + MENDING_MODIFIER, + STOMACH_SIZE_MULTIPLIER, LEARNING_FOCUS, ARMOR_BASH, ARMOR_CUT, @@ -242,6 +254,8 @@ class enchant_cache : public enchantment double modify_value( const skill_id &mod_val, double value ) const; units::energy modify_value( enchant_vals::mod mod_val, units::energy value ) const; units::mass modify_value( enchant_vals::mod mod_val, units::mass value ) const; + units::volume modify_value( enchant_vals::mod mod_val, units::volume value ) const; + time_duration modify_value( enchant_vals::mod mod_val, time_duration value ) const; // adds two enchantments together and ignores their conditions void force_add( const enchantment &rhs, const Character &guy ); void force_add( const enchantment &rhs ); diff --git a/src/melee.cpp b/src/melee.cpp index fa4ac6e53c09a..36c49800ef2a0 100644 --- a/src/melee.cpp +++ b/src/melee.cpp @@ -938,7 +938,9 @@ bool Character::melee_attack_abstract( Creature &t, bool allow_special, /** @EFFECT_MELEE reduces stamina cost of melee attacks */ const int deft_bonus = !hits && has_trait( trait_DEFT ) ? 50 : 0; const int base_stam = get_base_melee_stamina_cost(); - const int total_stam = get_total_melee_stamina_cost(); + const int total_stam = enchantment_cache->modify_value( + enchant_vals::mod::MELEE_STAMINA_CONSUMPTION, + get_total_melee_stamina_cost() ); burn_energy_arms( std::min( -50, total_stam + deft_bonus ) ); add_msg_debug( debugmode::DF_MELEE, "Stamina burn base/total (capped at -50): %d/%d", base_stam, diff --git a/src/stomach.cpp b/src/stomach.cpp index 272413de4d67e..a8e542ce0226d 100644 --- a/src/stomach.cpp +++ b/src/stomach.cpp @@ -304,7 +304,8 @@ void stomach_contents::deserialize( const JsonObject &jo ) units::volume stomach_contents::capacity( const Character &owner ) const { - return max_volume * owner.mutation_value( "stomach_size_multiplier" ); + return owner.enchantment_cache->modify_value( enchant_vals::mod::STOMACH_SIZE_MULTIPLIER, + max_volume * owner.mutation_value( "stomach_size_multiplier" ) ); } units::volume stomach_contents::stomach_remaining( const Character &owner ) const diff --git a/src/suffer.cpp b/src/suffer.cpp index 39129a7c70bed..0c82b5db39192 100644 --- a/src/suffer.cpp +++ b/src/suffer.cpp @@ -1958,6 +1958,9 @@ void Character::mend( int rate_multiplier ) healing_factor *= mutation_value( "mending_modifier" ); + healing_factor = enchantment_cache->modify_value( enchant_vals::mod::MENDING_MODIFIER, + healing_factor ); + add_msg_debug( debugmode::DF_CHAR_HEALTH, "Limb mend healing factor: %.2f", healing_factor ); if( healing_factor <= 0.0f ) { // The section below assumes positive healing rate