From 50232326d04cc92a548d895962f7a01e38b99a0b Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 19:34:03 +0300 Subject: [PATCH 01/20] Add warning for enchantment name migration --- src/magic_enchantment.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/magic_enchantment.cpp b/src/magic_enchantment.cpp index b1e6b5990830..70b4b858691b 100644 --- a/src/magic_enchantment.cpp +++ b/src/magic_enchantment.cpp @@ -144,17 +144,18 @@ namespace io // *INDENT-ON* } // namespace io -static void migrate_ench_vals_enums( std::string &s ) +static std::string migrate_ench_vals_enums( const std::string &s ) { if( s == "ITEM_ATTACK_SPEED" ) { - s = "ITEM_ATTACK_COST"; + return "ITEM_ATTACK_COST"; } else if( s == "ATTACK_SPEED" ) { - s = "ATTACK_COST"; + return "ATTACK_COST"; } else if( s == "MAX_MANA" ) { - s = "MANA_CAP"; + return "MANA_CAP"; } else if( s == "REGEN_MANA" ) { - s = "MANA_REGEN"; + return "MANA_REGEN"; } + return s; } namespace @@ -267,8 +268,15 @@ void enchantment::load( const JsonObject &jo, const std::string & ) if( jo.has_array( "values" ) ) { for( const JsonObject value_obj : jo.get_array( "values" ) ) { std::string value_raw = value_obj.get_string( "value" ); - migrate_ench_vals_enums( value_raw ); - const enchant_vals::mod value = io::string_to_enum( value_raw ); + std::string value_new = migrate_ench_vals_enums( value_raw ); + if( json_report_strict && value_new != value_raw ) { + try { + value_obj.throw_error( string_format( "%s has been renamed to %s", value_raw, value_new ) ); + } catch( const std::exception &e ) { + debugmsg( "%s", e.what() ); + } + } + const enchant_vals::mod value = io::string_to_enum( value_new ); const int add = value_obj.get_int( "add", 0 ); const double mult = value_obj.get_float( "multiply", 0.0 ); From 510645d57f2f0d00515038d898980aba99b058fd Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 19:35:23 +0300 Subject: [PATCH 02/20] Cull unimplemented enchantments list --- doc/MAGIC.md | 23 ----------------------- src/magic_enchantment.cpp | 23 +---------------------- src/magic_enchantment.h | 21 --------------------- 3 files changed, 1 insertion(+), 66 deletions(-) diff --git a/doc/MAGIC.md b/doc/MAGIC.md index 1d9b28072de8..430fe89373c4 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -433,27 +433,9 @@ TODO: docs for each TODO: some of these are broken/unimplemented -* BIONIC_POWER -* MAX_STAMINA -* REGEN_STAMINA -* MAX_HP -* REGEN_HP * THIRST * FATIGUE -* PAIN * BONUS_DODGE -* BONUS_BLOCK -* BONUS_DAMAGE -* ATTACK_NOISE -* SPELL_NOISE -* SHOUT_NOISE -* FOOTSTEP_NOISE -* SIGHT_RANGE -* CARRY_WEIGHT -* CARRY_VOLUME -* SOCIAL_LIE -* SOCIAL_PERSUADE -* SOCIAL_INTIMIDATE * ARMOR_BASH * ARMOR_CUT * ARMOR_STAB @@ -481,11 +463,6 @@ Effects for the item that has the enchantment: * ITEM_ARMOR_ELEC * ITEM_ARMOR_ACID * ITEM_ARMOR_BIO -* ITEM_WEIGHT -* ITEM_ENCUMBRANCE -* ITEM_VOLUME -* ITEM_COVERAGE -* ITEM_WET_PROTECTION ## Examples ```json diff --git a/src/magic_enchantment.cpp b/src/magic_enchantment.cpp index 70b4b858691b..b50391bb92fd 100644 --- a/src/magic_enchantment.cpp +++ b/src/magic_enchantment.cpp @@ -81,27 +81,11 @@ namespace io case enchant_vals::mod::METABOLISM: return "METABOLISM"; case enchant_vals::mod::MANA_CAP: return "MANA_CAP"; case enchant_vals::mod::MANA_REGEN: return "MANA_REGEN"; - case enchant_vals::mod::BIONIC_POWER: return "BIONIC_POWER"; case enchant_vals::mod::MAX_STAMINA: return "MAX_STAMINA"; case enchant_vals::mod::REGEN_STAMINA: return "REGEN_STAMINA"; - case enchant_vals::mod::MAX_HP: return "MAX_HP"; - case enchant_vals::mod::REGEN_HP: return "REGEN_HP"; case enchant_vals::mod::THIRST: return "THIRST"; case enchant_vals::mod::FATIGUE: return "FATIGUE"; - case enchant_vals::mod::PAIN: return "PAIN"; - case enchant_vals::mod::BONUS_DAMAGE: return "BONUS_DAMAGE"; - case enchant_vals::mod::BONUS_BLOCK: return "BONUS_BLOCK"; case enchant_vals::mod::BONUS_DODGE: return "BONUS_DODGE"; - case enchant_vals::mod::ATTACK_NOISE: return "ATTACK_NOISE"; - case enchant_vals::mod::SPELL_NOISE: return "SPELL_NOISE"; - case enchant_vals::mod::SHOUT_NOISE: return "SHOUT_NOISE"; - case enchant_vals::mod::FOOTSTEP_NOISE: return "FOOTSTEP_NOISE"; - case enchant_vals::mod::SIGHT_RANGE: return "SIGHT_RANGE"; - case enchant_vals::mod::CARRY_WEIGHT: return "CARRY_WEIGHT"; - case enchant_vals::mod::CARRY_VOLUME: return "CARRY_VOLUME"; - case enchant_vals::mod::SOCIAL_LIE: return "SOCIAL_LIE"; - case enchant_vals::mod::SOCIAL_PERSUADE: return "SOCIAL_PERSUADE"; - case enchant_vals::mod::SOCIAL_INTIMIDATE: return "SOCIAL_INTIMIDATE"; case enchant_vals::mod::ARMOR_ACID: return "ARMOR_ACID"; case enchant_vals::mod::ARMOR_BASH: return "ARMOR_BASH"; case enchant_vals::mod::ARMOR_BIO: return "ARMOR_BIO"; @@ -114,7 +98,7 @@ namespace io case enchant_vals::mod::ITEM_DAMAGE_BASH: return "ITEM_DAMAGE_BASH"; case enchant_vals::mod::ITEM_DAMAGE_CUT: return "ITEM_DAMAGE_CUT"; case enchant_vals::mod::ITEM_DAMAGE_STAB: return "ITEM_DAMAGE_STAB"; - case enchant_vals::mod::ITEM_DAMAGE_BULLET: return "ITEM_DAMAGE_BULLET"; + case enchant_vals::mod::ITEM_DAMAGE_BULLET: return "ITEM_DAMAGE_BULLET"; case enchant_vals::mod::ITEM_DAMAGE_HEAT: return "ITEM_DAMAGE_HEAT"; case enchant_vals::mod::ITEM_DAMAGE_COLD: return "ITEM_DAMAGE_COLD"; case enchant_vals::mod::ITEM_DAMAGE_ELEC: return "ITEM_DAMAGE_ELEC"; @@ -130,12 +114,7 @@ namespace io case enchant_vals::mod::ITEM_ARMOR_ELEC: return "ITEM_ARMOR_ELEC"; case enchant_vals::mod::ITEM_ARMOR_ACID: return "ITEM_ARMOR_ACID"; case enchant_vals::mod::ITEM_ARMOR_BIO: return "ITEM_ARMOR_BIO"; - case enchant_vals::mod::ITEM_WEIGHT: return "ITEM_WEIGHT"; - case enchant_vals::mod::ITEM_ENCUMBRANCE: return "ITEM_ENCUMBRANCE"; - case enchant_vals::mod::ITEM_VOLUME: return "ITEM_VOLUME"; - case enchant_vals::mod::ITEM_COVERAGE: return "ITEM_COVERAGE"; case enchant_vals::mod::ITEM_ATTACK_COST: return "ITEM_ATTACK_COST"; - case enchant_vals::mod::ITEM_WET_PROTECTION: return "ITEM_WET_PROTECTION"; case enchant_vals::mod::NUM_MOD: break; } debugmsg( "Invalid enchant_vals::mod" ); diff --git a/src/magic_enchantment.h b/src/magic_enchantment.h index f0963d3fa7d5..ffffcf5d4d2f 100644 --- a/src/magic_enchantment.h +++ b/src/magic_enchantment.h @@ -35,27 +35,11 @@ enum class mod : int { METABOLISM, MANA_CAP, MANA_REGEN, - BIONIC_POWER, MAX_STAMINA, REGEN_STAMINA, - MAX_HP, - REGEN_HP, THIRST, FATIGUE, - PAIN, BONUS_DODGE, - BONUS_BLOCK, - BONUS_DAMAGE, - ATTACK_NOISE, - SPELL_NOISE, - SHOUT_NOISE, - FOOTSTEP_NOISE, - SIGHT_RANGE, - CARRY_WEIGHT, - CARRY_VOLUME, - SOCIAL_LIE, - SOCIAL_PERSUADE, - SOCIAL_INTIMIDATE, ARMOR_BASH, ARMOR_CUT, ARMOR_STAB, @@ -85,12 +69,7 @@ enum class mod : int { ITEM_ARMOR_ELEC, ITEM_ARMOR_ACID, ITEM_ARMOR_BIO, - ITEM_WEIGHT, - ITEM_ENCUMBRANCE, - ITEM_VOLUME, - ITEM_COVERAGE, ITEM_ATTACK_COST, - ITEM_WET_PROTECTION, NUM_MOD }; } // namespace enchant_vals From 6fe4dc2f21634a5a3361163b36685461c75d2524 Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 20:40:06 +0300 Subject: [PATCH 03/20] Implement STAMINA_CAP and STAMINA_REGEN --- doc/MAGIC.md | 12 ++++++++++++ src/character.cpp | 10 +++++++--- src/magic_enchantment.cpp | 10 ++++++++-- src/magic_enchantment.h | 4 ++-- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/doc/MAGIC.md b/doc/MAGIC.md index 430fe89373c4..4912b4ecd7e6 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -418,6 +418,18 @@ This modifier ignores `add` field. `base_value` here is character's base mana gain rate modified by traits. The final value cannot go below 0. +##### STAMINA_CAP +Stamina capacity. +This modifier ignores `add` field. +`base_value` here is character's base stamina capacity modified by traits. +The final value cannot go below 10% of `PLAYER_MAX_STAMINA`. + +##### STAMINA_REGEN +Stamina regeneration rate. +This modifier ignores `add` field. +`base_value` here is character's base stamina gain rate modified by mouth encumbrance. +The final value cannot go below 0. + #### Item values ##### ITEM_ATTACK_COST diff --git a/src/character.cpp b/src/character.cpp index 8aadd44ebe79..850879bab8a7 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -7112,9 +7112,11 @@ int Character::get_stamina_max() const { static const std::string player_max_stamina( "PLAYER_MAX_STAMINA" ); static const std::string max_stamina_modifier( "max_stamina_modifier" ); - int maxStamina = get_option< int >( player_max_stamina ); + const int baseMaxStamina = get_option< int >( player_max_stamina ); + int maxStamina = baseMaxStamina; maxStamina *= Character::mutation_value( max_stamina_modifier ); - return maxStamina; + maxStamina += bonus_from_enchantments( maxStamina, enchant_vals::mod::STAMINA_CAP ); + return std::max( baseMaxStamina / 10, maxStamina ); } void Character::set_stamina( int new_stamina ) @@ -7191,7 +7193,8 @@ void Character::update_stamina( int turns ) // Recover some stamina every turn. // max stamina modifers from mutation also affect stamina multi float stamina_multiplier = 1.0f + mutation_value( stamina_regen_modifier ) + - ( mutation_value( "max_stamina_modifier" ) - 1.0f ); + ( mutation_value( "max_stamina_modifier" ) - 1.0f ) + + bonus_from_enchantments( 1.0, enchant_vals::mod::STAMINA_REGEN ); // But mouth encumbrance interferes, even with mutated stamina. stamina_recovery += stamina_multiplier * std::max( 1.0f, base_regen_rate - ( encumb( bp_mouth ) / 5.0f ) ); @@ -7210,6 +7213,7 @@ void Character::update_stamina( int turns ) // at 50% stamina its -10 (50%), cuts by 25% at 25% stamina stamina_recovery += current_stim / 5.0f * get_stamina() / get_stamina_max(); } + stamina_recovery = std::max( 0.0f, stamina_recovery ); const int max_stam = get_stamina_max(); if( get_power_level() >= 3_kJ && has_active_bionic( bio_gills ) ) { diff --git a/src/magic_enchantment.cpp b/src/magic_enchantment.cpp index b50391bb92fd..ece3ce21cc5e 100644 --- a/src/magic_enchantment.cpp +++ b/src/magic_enchantment.cpp @@ -81,8 +81,8 @@ namespace io case enchant_vals::mod::METABOLISM: return "METABOLISM"; case enchant_vals::mod::MANA_CAP: return "MANA_CAP"; case enchant_vals::mod::MANA_REGEN: return "MANA_REGEN"; - case enchant_vals::mod::MAX_STAMINA: return "MAX_STAMINA"; - case enchant_vals::mod::REGEN_STAMINA: return "REGEN_STAMINA"; + case enchant_vals::mod::STAMINA_CAP: return "STAMINA_CAP"; + case enchant_vals::mod::STAMINA_REGEN: return "STAMINA_REGEN"; case enchant_vals::mod::THIRST: return "THIRST"; case enchant_vals::mod::FATIGUE: return "FATIGUE"; case enchant_vals::mod::BONUS_DODGE: return "BONUS_DODGE"; @@ -133,6 +133,10 @@ static std::string migrate_ench_vals_enums( const std::string &s ) return "MANA_CAP"; } else if( s == "REGEN_MANA" ) { return "MANA_REGEN"; + } else if( s == "MAX_STAMINA" ) { + return "STAMINA_CAP"; + } else if( s == "REGEN_STAMINA" ) { + return "STAMINA_REGEN"; } return s; } @@ -424,6 +428,8 @@ double enchantment::calc_bonus( enchant_vals::mod value, double base, bool round switch( value ) { case enchant_vals::mod::METABOLISM: case enchant_vals::mod::MANA_REGEN: + case enchant_vals::mod::STAMINA_CAP: + case enchant_vals::mod::STAMINA_REGEN: use_add = false; break; default: diff --git a/src/magic_enchantment.h b/src/magic_enchantment.h index ffffcf5d4d2f..f37b79cf84de 100644 --- a/src/magic_enchantment.h +++ b/src/magic_enchantment.h @@ -35,8 +35,8 @@ enum class mod : int { METABOLISM, MANA_CAP, MANA_REGEN, - MAX_STAMINA, - REGEN_STAMINA, + STAMINA_CAP, + STAMINA_REGEN, THIRST, FATIGUE, BONUS_DODGE, From d520707657fe46ab03d79504f28218f8910949ad Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 20:53:46 +0300 Subject: [PATCH 04/20] Implement THIRST and FATIGUE --- doc/MAGIC.md | 14 ++++++++++++-- src/character.cpp | 6 ++++-- src/magic_enchantment.cpp | 2 ++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/doc/MAGIC.md b/doc/MAGIC.md index 4912b4ecd7e6..80cef7379b48 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -430,6 +430,18 @@ This modifier ignores `add` field. `base_value` here is character's base stamina gain rate modified by mouth encumbrance. The final value cannot go below 0. +##### THIRST +Thirst gain rate. +This modifier ignores `add` field. +`base_value` here is character's base thirst gain rate. +The final value cannot go below 0. + +##### FATIGUE +Fatigue gain rate. +This modifier ignores `add` field. +`base_value` here is character's base fatigue gain rate. +The final value cannot go below 0. + #### Item values ##### ITEM_ATTACK_COST @@ -445,8 +457,6 @@ TODO: docs for each TODO: some of these are broken/unimplemented -* THIRST -* FATIGUE * BONUS_DODGE * ARMOR_BASH * ARMOR_CUT diff --git a/src/character.cpp b/src/character.cpp index 850879bab8a7..3dd61c3d52a8 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -4917,7 +4917,8 @@ needs_rates Character::calc_needs_rates() const static const std::string player_thirst_rate( "PLAYER_THIRST_RATE" ); rates.thirst = get_option< float >( player_thirst_rate ); static const std::string thirst_modifier( "thirst_modifier" ); - rates.thirst *= 1.0f + mutation_value( thirst_modifier ); + rates.thirst *= 1.0f + mutation_value( thirst_modifier ) + + bonus_from_enchantments( 1.0, enchant_vals::mod::THIRST ); static const std::string slows_thirst( "SLOWS_THIRST" ); if( worn_with_flag( slows_thirst ) ) { rates.thirst *= 0.7f; @@ -4926,7 +4927,8 @@ needs_rates Character::calc_needs_rates() const static const std::string player_fatigue_rate( "PLAYER_FATIGUE_RATE" ); rates.fatigue = get_option< float >( player_fatigue_rate ); static const std::string fatigue_modifier( "fatigue_modifier" ); - rates.fatigue *= 1.0f + mutation_value( fatigue_modifier ); + rates.fatigue *= 1.0f + mutation_value( fatigue_modifier ) + + bonus_from_enchantments( 1.0, enchant_vals::mod::FATIGUE ); // Note: intentionally not in metabolic rate if( has_recycler ) { diff --git a/src/magic_enchantment.cpp b/src/magic_enchantment.cpp index ece3ce21cc5e..280f6e991828 100644 --- a/src/magic_enchantment.cpp +++ b/src/magic_enchantment.cpp @@ -430,6 +430,8 @@ double enchantment::calc_bonus( enchant_vals::mod value, double base, bool round case enchant_vals::mod::MANA_REGEN: case enchant_vals::mod::STAMINA_CAP: case enchant_vals::mod::STAMINA_REGEN: + case enchant_vals::mod::THIRST: + case enchant_vals::mod::FATIGUE: use_add = false; break; default: From 3f8d483e1707e1ba38ee1a2b712a74edd49671f5 Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 21:17:48 +0300 Subject: [PATCH 05/20] Add docs for BONUS_DODGE --- doc/MAGIC.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/MAGIC.md b/doc/MAGIC.md index 80cef7379b48..c0079cf289d7 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -442,6 +442,12 @@ This modifier ignores `add` field. `base_value` here is character's base fatigue gain rate. The final value cannot go below 0. +##### BONUS_DODGE +Dodges per turn. +`base_value` here is character's base dodges per turn. +The final value can go below 0, which results in penalty to dodge roll. + + #### Item values ##### ITEM_ATTACK_COST @@ -457,7 +463,6 @@ TODO: docs for each TODO: some of these are broken/unimplemented -* BONUS_DODGE * ARMOR_BASH * ARMOR_CUT * ARMOR_STAB From cce233aebb4f1d02a4e97fb9013079ddcc29accd Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 21:27:29 +0300 Subject: [PATCH 06/20] Constify some function arguments --- src/character.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/character.cpp b/src/character.cpp index 3dd61c3d52a8..3c62875485cb 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -7993,7 +7993,9 @@ static void destroyed_armor_msg( Character &who, const std::string &pre_damage_n pre_damage_name ); } -static void item_armor_enchantment_adjust( Character &guy, damage_unit &du, item &armor ) +static void item_armor_enchantment_adjust( + const Character &guy, damage_unit &du, const item &armor +) { switch( du.type ) { case DT_ACID: @@ -8031,7 +8033,7 @@ static void item_armor_enchantment_adjust( Character &guy, damage_unit &du, item // adjusts damage unit depending on type by enchantments. // the ITEM_ enchantments only affect the damage resistance for that one item, while the others affect all of them -static void armor_enchantment_adjust( Character &guy, damage_unit &du ) +static void armor_enchantment_adjust( const Character &guy, damage_unit &du ) { switch( du.type ) { case DT_ACID: From e56ea052f76d5c8224028fe7afd7f0cb22b8ad76 Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 21:27:37 +0300 Subject: [PATCH 07/20] Add docs for ITEM_ARMOR_X --- doc/MAGIC.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/doc/MAGIC.md b/doc/MAGIC.md index c0079cf289d7..3f04f36e12f5 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -456,6 +456,21 @@ Ignores condition / location, and is always active. `base_value` here is base item attack cost. Note that the final value cannot go below 0. +##### ITEM_ARMOR_X +Incoming damage modifier for this item, applied before the damage is absorbed by the item. +Note that `base_value` here is incoming damage value of corresponding type, +so positive `add` and greater than 1 `mul` will **increase** damage received by the character. +Each damage type has its own enchant value: +* `ITEM_ARMOR_ACID` +* `ITEM_ARMOR_BASH` +* `ITEM_ARMOR_BIO` +* `ITEM_ARMOR_BULLET` +* `ITEM_ARMOR_COLD` +* `ITEM_ARMOR_CUT` +* `ITEM_ARMOR_ELEC` +* `ITEM_ARMOR_HEAT` +* `ITEM_ARMOR_STAB` + ##### TODO TODO: docs for each @@ -482,14 +497,6 @@ Effects for the item that has the enchantment: * ITEM_DAMAGE_ACID * ITEM_DAMAGE_BIO * ITEM_DAMAGE_AP -* ITEM_ARMOR_BASH -* ITEM_ARMOR_CUT -* ITEM_ARMOR_STAB -* ITEM_ARMOR_HEAT -* ITEM_ARMOR_COLD -* ITEM_ARMOR_ELEC -* ITEM_ARMOR_ACID -* ITEM_ARMOR_BIO ## Examples ```json From 9da0daab638ac6c390426190ecdc00a4d7d10c8b Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 22:06:30 +0300 Subject: [PATCH 08/20] Add docs for ARMOR_X --- doc/MAGIC.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/doc/MAGIC.md b/doc/MAGIC.md index 3f04f36e12f5..a63548e26e54 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -447,6 +447,21 @@ Dodges per turn. `base_value` here is character's base dodges per turn. The final value can go below 0, which results in penalty to dodge roll. +##### ARMOR_X +Incoming damage modifier. +Applied after Active Defense System bionic but before the damage is absorbed by items. +Note that `base_value` here is incoming damage value of corresponding type, +so positive `add` and greater than 1 `mul` will **increase** damage received by the character. +Each damage type has its own enchant value: +* `ARMOR_ACID` +* `ARMOR_BASH` +* `ARMOR_BIO` +* `ARMOR_BULLET` +* `ARMOR_COLD` +* `ARMOR_CUT` +* `ARMOR_ELEC` +* `ARMOR_HEAT` +* `ARMOR_STAB` #### Item values @@ -478,15 +493,6 @@ TODO: docs for each TODO: some of these are broken/unimplemented -* ARMOR_BASH -* ARMOR_CUT -* ARMOR_STAB -* ARMOR_HEAT -* ARMOR_COLD -* ARMOR_ELEC -* ARMOR_ACID -* ARMOR_BIO - Effects for the item that has the enchantment: * ITEM_DAMAGE_BASH * ITEM_DAMAGE_CUT From e78a29ed1986a6e529d35eb0ddd85e98748f6c5d Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 22:28:48 +0300 Subject: [PATCH 09/20] Implement ITEM_DAMAGE_BASH, ITEM_DAMAGE_CUT, ITEM_DAMAGE_STAB --- doc/MAGIC.md | 27 ++++++++++----------------- src/item.cpp | 14 ++++++++++++++ src/magic_enchantment.cpp | 7 ------- src/magic_enchantment.h | 7 ------- 4 files changed, 24 insertions(+), 31 deletions(-) diff --git a/doc/MAGIC.md b/doc/MAGIC.md index a63548e26e54..277fa843953b 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -471,6 +471,16 @@ Ignores condition / location, and is always active. `base_value` here is base item attack cost. Note that the final value cannot go below 0. +##### ITEM_DAMAGE_X +Melee damage of this item. +Ignores condition / location, and is always active. +`base_value` here is base item damage of corresponding type. +Note that the final value cannot go below 0. +Only some damage types are supported: +* `ITEM_DAMAGE_BASH` +* `ITEM_DAMAGE_CUT` +* `ITEM_DAMAGE_STAB` + ##### ITEM_ARMOR_X Incoming damage modifier for this item, applied before the damage is absorbed by the item. Note that `base_value` here is incoming damage value of corresponding type, @@ -486,23 +496,6 @@ Each damage type has its own enchant value: * `ITEM_ARMOR_HEAT` * `ITEM_ARMOR_STAB` -##### TODO - -TODO: docs for each - -TODO: some of these are broken/unimplemented - - -Effects for the item that has the enchantment: -* ITEM_DAMAGE_BASH -* ITEM_DAMAGE_CUT -* ITEM_DAMAGE_STAB -* ITEM_DAMAGE_HEAT -* ITEM_DAMAGE_COLD -* ITEM_DAMAGE_ELEC -* ITEM_DAMAGE_ACID -* ITEM_DAMAGE_BIO -* ITEM_DAMAGE_AP ## Examples ```json diff --git a/src/item.cpp b/src/item.cpp index a52f50b3cba3..ee9853ae360f 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -5162,6 +5162,20 @@ int item::damage_melee( damage_type dt ) const } + switch( dt ) { + case DT_BASH: + res += bonus_from_enchantments_wielded( res, enchant_vals::mod::ITEM_DAMAGE_BASH, true ); + break; + case DT_CUT: + res += bonus_from_enchantments_wielded( res, enchant_vals::mod::ITEM_DAMAGE_CUT, true ); + break; + case DT_STAB: + res += bonus_from_enchantments_wielded( res, enchant_vals::mod::ITEM_DAMAGE_STAB, true ); + break; + default: + break; + } + return std::max( res, 0 ); } diff --git a/src/magic_enchantment.cpp b/src/magic_enchantment.cpp index 280f6e991828..02c2eadf5bd7 100644 --- a/src/magic_enchantment.cpp +++ b/src/magic_enchantment.cpp @@ -98,13 +98,6 @@ namespace io case enchant_vals::mod::ITEM_DAMAGE_BASH: return "ITEM_DAMAGE_BASH"; case enchant_vals::mod::ITEM_DAMAGE_CUT: return "ITEM_DAMAGE_CUT"; case enchant_vals::mod::ITEM_DAMAGE_STAB: return "ITEM_DAMAGE_STAB"; - case enchant_vals::mod::ITEM_DAMAGE_BULLET: return "ITEM_DAMAGE_BULLET"; - case enchant_vals::mod::ITEM_DAMAGE_HEAT: return "ITEM_DAMAGE_HEAT"; - case enchant_vals::mod::ITEM_DAMAGE_COLD: return "ITEM_DAMAGE_COLD"; - case enchant_vals::mod::ITEM_DAMAGE_ELEC: return "ITEM_DAMAGE_ELEC"; - case enchant_vals::mod::ITEM_DAMAGE_ACID: return "ITEM_DAMAGE_ACID"; - case enchant_vals::mod::ITEM_DAMAGE_BIO: return "ITEM_DAMAGE_BIO"; - case enchant_vals::mod::ITEM_DAMAGE_AP: return "ITEM_DAMAGE_AP"; case enchant_vals::mod::ITEM_ARMOR_BASH: return "ITEM_ARMOR_BASH"; case enchant_vals::mod::ITEM_ARMOR_CUT: return "ITEM_ARMOR_CUT"; case enchant_vals::mod::ITEM_ARMOR_STAB: return "ITEM_ARMOR_STAB"; diff --git a/src/magic_enchantment.h b/src/magic_enchantment.h index f37b79cf84de..49c7999c9617 100644 --- a/src/magic_enchantment.h +++ b/src/magic_enchantment.h @@ -53,13 +53,6 @@ enum class mod : int { ITEM_DAMAGE_BASH, ITEM_DAMAGE_CUT, ITEM_DAMAGE_STAB, - ITEM_DAMAGE_BULLET, - ITEM_DAMAGE_HEAT, - ITEM_DAMAGE_COLD, - ITEM_DAMAGE_ELEC, - ITEM_DAMAGE_ACID, - ITEM_DAMAGE_BIO, - ITEM_DAMAGE_AP, ITEM_ARMOR_BASH, ITEM_ARMOR_CUT, ITEM_ARMOR_STAB, From ca7fbe9c478c9820dbd5426ce48b25721bf3e68d Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 22:39:53 +0300 Subject: [PATCH 10/20] Update ToC in MAGIC.md --- doc/MAGIC.md | 50 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/doc/MAGIC.md b/doc/MAGIC.md index 277fa843953b..ba00f9381ff9 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -1,13 +1,45 @@ # Spells, enchantments and other custom effects -- [Spells](#Spells) - * [Currently Implemented Effects and special rules](#Currently-Implemented-Effects-and-special-rules) - * [Spells that level up](#Spells-that-level-up) - * [Learning spells](#Learning-spells) - * [Spells in professions and NPC classes](#Spells-in-professions-and-NPC-classes) - * [Spells in monsters](#Spells-in-monsters) -- [Enchantments](#Enchantments) - * [Fields](#Fields) - * [Examples](#Examples) +- [Spells](#spells) + - [Currently Implemented Effects and special rules](#currently-implemented-effects-and-special-rules) + - [Spells that level up](#spells-that-level-up) + - [Learning Spells](#learning-spells) + - [Spells in professions and NPC classes](#spells-in-professions-and-npc-classes) + - [Spells in monsters](#spells-in-monsters) +- [Enchantments](#enchantments) + - [id](#id) + - [has](#has) + - [condition](#condition) + - [emitter](#emitter) + - [ench\_effects](#ench_effects) + - [hit\_you\_effect](#hit_you_effect) + - [hit\_me\_effect](#hit_me_effect) + - [mutations](#mutations) + - [intermittent\_activation](#intermittent_activation) + - [values](#values) + - [IDs of modifiable values](#ids-of-modifiable-values) + - [Character values](#character-values) + - [STRENGTH](#strength) + - [DEXTERITY](#dexterity) + - [PERCEPTION](#perception) + - [INTELLIGENCE](#intelligence) + - [SPEED](#speed) + - [ATTACK\_COST](#attack_cost) + - [MOVE\_COST](#move_cost) + - [METABOLISM](#metabolism) + - [MANA\_CAP](#mana_cap) + - [MANA\_REGEN](#mana_regen) + - [STAMINA\_CAP](#stamina_cap) + - [STAMINA\_REGEN](#stamina_regen) + - [THIRST](#thirst) + - [FATIGUE](#fatigue) + - [BONUS\_DODGE](#bonus_dodge) + - [ARMOR\_X](#armor_x) + - [Item values](#item-values) + - [ITEM\_ATTACK\_COST](#item_attack_cost) + - [ITEM\_DAMAGE\_X](#item_damage_x) + - [ITEM\_ARMOR\_X](#item_armor_x) + - [Examples](#examples) + # Spells From 6435269290423ce99c12edc70807aeae926b7b01 Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 23:32:00 +0300 Subject: [PATCH 11/20] Tests for STAMINA enchants --- data/mods/TEST_DATA/relics.json | 12 ++++ src/character.cpp | 1 + tests/enchantment_test.cpp | 119 ++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+) diff --git a/data/mods/TEST_DATA/relics.json b/data/mods/TEST_DATA/relics.json index bcc346e95252..3850937c3a12 100644 --- a/data/mods/TEST_DATA/relics.json +++ b/data/mods/TEST_DATA/relics.json @@ -108,5 +108,17 @@ } ] } + }, + { + "type": "GENERIC", + "id": "test_relic_mods_stamina", + "copy-from": "test_relic_base", + "name": "TEST relic mods stamina rate", + "relic_data": { + "passive_effects": [ + { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "STAMINA_CAP", "multiply": -0.1 } ] }, + { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "STAMINA_REGEN", "multiply": -0.1 } ] } + ] + } } ] diff --git a/src/character.cpp b/src/character.cpp index 3c62875485cb..040feecae913 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -7213,6 +7213,7 @@ void Character::update_stamina( int turns ) // At -100 stim it inflicts -20 malus to regen at 100% stamina, // effectivly countering stamina gain of default 20, // at 50% stamina its -10 (50%), cuts by 25% at 25% stamina + // FIXME: this formula is only suitable for advancing by 1 turn stamina_recovery += current_stim / 5.0f * get_stamina() / get_stamina_max(); } stamina_recovery = std::max( 0.0f, stamina_recovery ); diff --git a/tests/enchantment_test.cpp b/tests/enchantment_test.cpp index 32a80149a286..6a3357a4ac61 100644 --- a/tests/enchantment_test.cpp +++ b/tests/enchantment_test.cpp @@ -555,3 +555,122 @@ TEST_CASE( "Mana pool", "[magic][enchantment][mana][bionic]" ) tests_mana_pool_section( it ); } } + +static float measure_stamina_gain_rate( Character &guy ) +{ + int gained_total = 0; + // Stamina regen rate is supposed to decrease over time as character gains stamina, + // so we measure 100 times on same level instead of doing update_stamina( 100 ) + for( int i = 0; i < 100; i++ ) { + guy.set_stamina( 0 ); + if( guy.get_stamina() != 0 ) { + // Hide this behind an if check to avoid spamming check counter + REQUIRE( guy.get_stamina() == 0 ); + } + guy.update_stamina( 1 ); + gained_total += guy.get_stamina(); + } + return gained_total / 100.0f; +} + +static void tests_stamina( Character &guy, + int cap_norm, int cap_exp, + float rate_norm, float rate_exp + ) +{ + guy.recalculate_enchantment_cache(); + advance_turn( guy ); + + std::string s_relic = "test_relic_mods_stamina"; + + REQUIRE( guy.get_stamina_max() == cap_norm ); + REQUIRE( measure_stamina_gain_rate( guy ) == Approx( rate_norm ) ); + + WHEN( "Character receives relic" ) { + give_item( guy, s_relic ); + THEN( "Stamina cap changes" ) { + CHECK( guy.get_stamina_max() == cap_exp ); + AND_WHEN( "Character loses relic" ) { + clear_items( guy ); + THEN( "Stamina cap goes back to normal" ) { + CHECK( guy.get_stamina_max() == cap_norm ); + } + } + } + THEN( "Stamina gain rate changes" ) { + CHECK( measure_stamina_gain_rate( guy ) == Approx( rate_exp ) ); + AND_WHEN( "Character loses relic" ) { + clear_items( guy ); + THEN( "Stamina gain rate goes back to normal" ) { + CHECK( measure_stamina_gain_rate( guy ) == Approx( rate_norm ) ); + } + } + } + } + WHEN( "Character receives 15 relics" ) { + for( int i = 0; i < 15; i++ ) { + give_item( guy, s_relic ); + } + THEN( "Stamina cap does not go below 0.1 of PLAYER_MAX_STAMINA" ) { + const int base_cap = get_option( "PLAYER_MAX_STAMINA" ); + CHECK( guy.get_stamina_max() == ( base_cap / 10 ) ); + } + THEN( "Stamina gain rate does not go below 0" ) { + CHECK( measure_stamina_gain_rate( guy ) == Approx( 0.0f ) ); + } + } +} + +TEST_CASE( "Enchantments modify stamina", "[magic][enchantment][stamina]" ) +{ + clear_all_state(); + Character &guy = get_player_character(); + clear_character( *guy.as_player(), true ); + + guy.recalculate_enchantment_cache(); + advance_turn( guy ); + + REQUIRE( guy.get_stim() == 0 ); + + const int normal_cap = get_option( "PLAYER_MAX_STAMINA" ); + REQUIRE( normal_cap == 10000 ); + REQUIRE( guy.get_stamina_max() == normal_cap ); + + const float normal_rate = get_option( "PLAYER_BASE_STAMINA_REGEN_RATE" ); + REQUIRE( normal_rate == Approx( 20.0f ) ); + REQUIRE( measure_stamina_gain_rate( guy ) == Approx( normal_rate ) ); + + guy.set_stamina( 0 ); + REQUIRE( guy.get_stamina() == 0 ); + + SECTION( "Clean character" ) { + tests_stamina( guy, 10000, 9000, 20.0f, 18.0f ); + } + SECTION( "Character with GOODCARDIO trait" ) { + trait_id tr( "GOODCARDIO" ); + guy.set_mutation( tr ); + REQUIRE( guy.has_trait( tr ) ); + + tests_stamina( guy, 12500, 11250, 25.0f, 23.0f ); + } + SECTION( "Character with PERSISTENCE_HUNTER trait" ) { + trait_id tr( "PERSISTENCE_HUNTER" ); + guy.set_mutation( tr ); + REQUIRE( guy.has_trait( tr ) ); + + tests_stamina( guy, 10000, 9000, 22.0f, 20.0f ); + } + SECTION( "Character with GOODCARDIO and PERSISTENCE_HUNTER traits" ) { + { + trait_id tr( "GOODCARDIO" ); + guy.set_mutation( tr ); + REQUIRE( guy.has_trait( tr ) ); + } + { + trait_id tr( "PERSISTENCE_HUNTER" ); + guy.set_mutation( tr ); + REQUIRE( guy.has_trait( tr ) ); + } + tests_stamina( guy, 12500, 11250, 27.0f, 25.0f ); + } +} From 8d6fc9e35268443b476a7b143640fb7db0590d28 Mon Sep 17 00:00:00 2001 From: Olanti Date: Fri, 30 Dec 2022 23:49:09 +0300 Subject: [PATCH 12/20] Tests for THIRST and FATIGUE enchants --- data/mods/TEST_DATA/relics.json | 18 +++++++ src/character.cpp | 5 ++ tests/enchantment_test.cpp | 91 +++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/data/mods/TEST_DATA/relics.json b/data/mods/TEST_DATA/relics.json index 3850937c3a12..40b0523b5831 100644 --- a/data/mods/TEST_DATA/relics.json +++ b/data/mods/TEST_DATA/relics.json @@ -120,5 +120,23 @@ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "STAMINA_REGEN", "multiply": -0.1 } ] } ] } + }, + { + "type": "GENERIC", + "id": "test_relic_mods_thirst", + "copy-from": "test_relic_base", + "name": "TEST relic mods thirst rate", + "relic_data": { + "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "THIRST", "multiply": -0.1 } ] } ] + } + }, + { + "type": "GENERIC", + "id": "test_relic_mods_fatigue", + "copy-from": "test_relic_base", + "name": "TEST relic mods fatigue rate", + "relic_data": { + "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "FATIGUE", "multiply": -0.1 } ] } ] + } } ] diff --git a/src/character.cpp b/src/character.cpp index 040feecae913..b20623a8a33c 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -4973,6 +4973,11 @@ needs_rates Character::calc_needs_rates() const rates.thirst *= 0.25f; } + rates.thirst = std::max( rates.thirst, 0.0f ); + rates.hunger = std::max( rates.hunger, 0.0f ); + rates.fatigue = std::max( rates.fatigue, 0.0f ); + rates.recovery = std::max( rates.recovery, 0.0f ); + return rates; } diff --git a/tests/enchantment_test.cpp b/tests/enchantment_test.cpp index 6a3357a4ac61..75131659ccc8 100644 --- a/tests/enchantment_test.cpp +++ b/tests/enchantment_test.cpp @@ -674,3 +674,94 @@ TEST_CASE( "Enchantments modify stamina", "[magic][enchantment][stamina]" ) tests_stamina( guy, 12500, 11250, 27.0f, 25.0f ); } } + +template +static void tests_need_rate( Character &guy, const std::string &s_relic, float norm, float exp, + F getter ) +{ + guy.recalculate_enchantment_cache(); + advance_turn( guy ); + + REQUIRE( getter( guy ) == Approx( norm ) ); + + WHEN( "Character receives relic" ) { + give_item( guy, s_relic ); + THEN( "Need rate changes" ) { + CHECK( getter( guy ) == Approx( exp ) ); + AND_WHEN( "Character loses relic" ) { + clear_items( guy ); + THEN( "Need rate goes back to normal" ) { + CHECK( getter( guy ) == Approx( norm ) ); + } + } + } + } + WHEN( "Character receives 15 relics" ) { + for( int i = 0; i < 15; i++ ) { + give_item( guy, s_relic ); + } + THEN( "Need rate does not go below 0" ) { + CHECK( getter( guy ) == Approx( 0.0f ) ); + } + } +} + +TEST_CASE( "Enchantments modify thirst rate", "[magic][enchantment][thirst]" ) +{ + clear_all_state(); + Character &guy = get_player_character(); + clear_character( *guy.as_player(), true ); + + guy.recalculate_enchantment_cache(); + advance_turn( guy ); + + std::string s_relic = "test_relic_mods_thirst"; + const auto getter = []( const Character & guy ) -> float { + return guy.calc_needs_rates().thirst; + }; + + const float normal_rate = get_option( "PLAYER_THIRST_RATE" ); + REQUIRE( normal_rate == Approx( 1.0f ) ); + REQUIRE( getter( guy ) == Approx( normal_rate ) ); + + SECTION( "Clean character" ) { + tests_need_rate( guy, s_relic, 1.0f, 0.9f, getter ); + } + SECTION( "Character with THIRST trait" ) { + trait_id tr( "THIRST" ); + guy.set_mutation( tr ); + REQUIRE( guy.has_trait( tr ) ); + + tests_need_rate( guy, s_relic, 1.5f, 1.4f, getter ); + } +} + +TEST_CASE( "Enchantments modify fatigue rate", "[magic][enchantment][fatigue]" ) +{ + clear_all_state(); + Character &guy = get_player_character(); + clear_character( *guy.as_player(), true ); + + guy.recalculate_enchantment_cache(); + advance_turn( guy ); + + std::string s_relic = "test_relic_mods_fatigue"; + const auto getter = []( const Character & guy ) -> float { + return guy.calc_needs_rates().fatigue; + }; + + const float normal_rate = get_option( "PLAYER_THIRST_RATE" ); + REQUIRE( normal_rate == Approx( 1.0f ) ); + REQUIRE( getter( guy ) == Approx( normal_rate ) ); + + SECTION( "Clean character" ) { + tests_need_rate( guy, s_relic, 1.0f, 0.9f, getter ); + } + SECTION( "Character with WAKEFUL trait" ) { + trait_id tr( "WAKEFUL" ); + guy.set_mutation( tr ); + REQUIRE( guy.has_trait( tr ) ); + + tests_need_rate( guy, s_relic, 0.85f, 0.75f, getter ); + } +} From 957ead1e7ca6a7fa0798520a09c3ffd1edcfe898 Mon Sep 17 00:00:00 2001 From: Olanti Date: Sat, 31 Dec 2022 01:21:35 +0300 Subject: [PATCH 13/20] Tests for BONUS_DODGE --- data/mods/TEST_DATA/relics.json | 9 ++++ tests/enchantment_test.cpp | 86 +++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/data/mods/TEST_DATA/relics.json b/data/mods/TEST_DATA/relics.json index 40b0523b5831..38aade910c91 100644 --- a/data/mods/TEST_DATA/relics.json +++ b/data/mods/TEST_DATA/relics.json @@ -138,5 +138,14 @@ "relic_data": { "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "FATIGUE", "multiply": -0.1 } ] } ] } + }, + { + "type": "GENERIC", + "id": "test_relic_mods_dodges", + "copy-from": "test_relic_base", + "name": "TEST relic mods dodges", + "relic_data": { + "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "BONUS_DODGE", "add": 1 } ] } ] + } } ] diff --git a/tests/enchantment_test.cpp b/tests/enchantment_test.cpp index 75131659ccc8..08a1dbbcf68e 100644 --- a/tests/enchantment_test.cpp +++ b/tests/enchantment_test.cpp @@ -765,3 +765,89 @@ TEST_CASE( "Enchantments modify fatigue rate", "[magic][enchantment][fatigue]" ) tests_need_rate( guy, s_relic, 0.85f, 0.75f, getter ); } } + +static void check_num_dodges( const Character &guy, int num ) +{ + CHECK( guy.get_num_dodges() == num ); + CHECK( guy.dodges_left == num ); +} + +static void tests_num_dodges( Character &guy ) +{ + guy.recalculate_enchantment_cache(); + + // Must have some moves to gain dodges + guy.moves = 1; + guy.dodges_left = 0; + + advance_turn( guy ); + + REQUIRE( guy.get_num_dodges_base() == 1 ); + REQUIRE( guy.get_num_dodges_bonus() == 0 ); + REQUIRE( guy.get_num_dodges() == 1 ); + REQUIRE( guy.dodges_left == 1 ); + + std::string s_relic = "test_relic_mods_dodges"; + + WHEN( "Character has no relics" ) { + THEN( "Dodges bonus remain unaffected" ) { + guy.moves = 1; + guy.dodges_left = 0; + advance_turn( guy ); + check_num_dodges( guy, 1 ); + } + } + WHEN( "Character receives relic" ) { + give_item( guy, s_relic ); + THEN( "Nothing changes" ) { + check_num_dodges( guy, 1 ); + } + AND_WHEN( "Turn passes" ) { + guy.moves = 1; + guy.dodges_left = 0; + advance_turn( guy ); + THEN( "Dodge bonus changes, dodges increase" ) { + check_num_dodges( guy, 2 ); + } + AND_WHEN( "Character loses relic" ) { + clear_items( guy ); + THEN( "Nothing changes" ) { + check_num_dodges( guy, 2 ); + } + AND_WHEN( "Turn passes" ) { + guy.moves = 1; + guy.dodges_left = 0; + advance_turn( guy ); + THEN( "Dodge bonus and dodge gain return to normal" ) { + check_num_dodges( guy, 1 ); + } + } + } + } + } + WHEN( "Character receives 10 relics" ) { + for( int i = 0; i < 10; i++ ) { + give_item( guy, s_relic ); + } + THEN( "Nothing changes" ) { + check_num_dodges( guy, 1 ); + } + AND_WHEN( "Turn passes" ) { + guy.moves = 1; + guy.dodges_left = 0; + advance_turn( guy ); + THEN( "Dodge bonus and dodge gain increase by 10" ) { + check_num_dodges( guy, 11 ); + } + } + } +} + +TEST_CASE( "Enchantments grant bonus dodges", "[magic][enchantment][dodge]" ) +{ + clear_all_state(); + Character &guy = get_player_character(); + clear_character( *guy.as_player(), true ); + + tests_num_dodges( guy ); +} From 184c70164254775bfe7a011ed6ca2869af5bd1e8 Mon Sep 17 00:00:00 2001 From: Olanti Date: Sat, 31 Dec 2022 01:44:34 +0300 Subject: [PATCH 14/20] Tests for ITEM_DAMAGE_X --- data/mods/TEST_DATA/relics.json | 27 ++++++++++++++++++++++++++ tests/enchantment_test.cpp | 34 +++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/data/mods/TEST_DATA/relics.json b/data/mods/TEST_DATA/relics.json index 38aade910c91..349bc29552ef 100644 --- a/data/mods/TEST_DATA/relics.json +++ b/data/mods/TEST_DATA/relics.json @@ -147,5 +147,32 @@ "relic_data": { "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "BONUS_DODGE", "add": 1 } ] } ] } + }, + { + "type": "GENERIC", + "id": "test_relic_mods_cut_dmg", + "copy-from": "test_balanced_sword", + "name": "TEST relic mods cut dmg", + "relic_data": { + "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "ITEM_DAMAGE_CUT", "multiply": -0.5, "add": 1 } ] } ] + } + }, + { + "type": "GENERIC", + "id": "test_relic_mods_stab_dmg", + "copy-from": "test_screwdriver", + "name": "TEST relic mods stab dmg", + "relic_data": { + "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "ITEM_DAMAGE_STAB", "multiply": -0.5, "add": 1 } ] } ] + } + }, + { + "type": "GENERIC", + "id": "test_relic_mods_bash_dmg", + "copy-from": "test_halligan", + "name": "TEST relic mods bash dmg", + "relic_data": { + "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "ITEM_DAMAGE_BASH", "multiply": -0.5, "add": 1 } ] } ] + } } ] diff --git a/tests/enchantment_test.cpp b/tests/enchantment_test.cpp index 08a1dbbcf68e..ce4a482c5ca7 100644 --- a/tests/enchantment_test.cpp +++ b/tests/enchantment_test.cpp @@ -19,10 +19,11 @@ static void advance_turn( Character &guy ) calendar::turn += 1_turns; } -static void give_item( Character &guy, const std::string &item_id ) +static item &give_item( Character &guy, const std::string &item_id ) { - guy.i_add( item( item_id ) ); + item &ret = guy.i_add( item( item_id ) ); guy.recalculate_enchantment_cache(); + return ret; } static void clear_items( Character &guy ) @@ -851,3 +852,32 @@ TEST_CASE( "Enchantments grant bonus dodges", "[magic][enchantment][dodge]" ) tests_num_dodges( guy ); } + +TEST_CASE( "Item enchantments modify item damage", "[magic][enchantment]" ) +{ + clear_all_state(); + Character &guy = get_player_character(); + clear_character( *guy.as_player(), true ); + + SECTION( "Cut damage" ) { + item &base = give_item( guy, "test_balanced_sword" ); + item &impr = give_item( guy, "test_relic_mods_cut_dmg" ); + + REQUIRE( base.damage_melee( damage_type::DT_CUT ) == 32 ); + CHECK( impr.damage_melee( damage_type::DT_CUT ) == 17 ); + } + SECTION( "Stab damage" ) { + item &base = give_item( guy, "test_screwdriver" ); + item &impr = give_item( guy, "test_relic_mods_stab_dmg" ); + + REQUIRE( base.damage_melee( damage_type::DT_STAB ) == 6 ); + CHECK( impr.damage_melee( damage_type::DT_STAB ) == 4 ); + } + SECTION( "Bash damage" ) { + item &base = give_item( guy, "test_halligan" ); + item &impr = give_item( guy, "test_relic_mods_bash_dmg" ); + + REQUIRE( base.damage_melee( damage_type::DT_BASH ) == 20 ); + CHECK( impr.damage_melee( damage_type::DT_BASH ) == 11 ); + } +} From 5295e108c37f3f4c09a8319bf75da294522225ff Mon Sep 17 00:00:00 2001 From: Olanti Date: Sat, 31 Dec 2022 02:23:32 +0300 Subject: [PATCH 15/20] Tests for ARMOR_X and ITEM_ARMOR_X --- data/mods/TEST_DATA/relics.json | 24 +++++++++++++ tests/enchantment_test.cpp | 63 +++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/data/mods/TEST_DATA/relics.json b/data/mods/TEST_DATA/relics.json index 349bc29552ef..27fbb4390acd 100644 --- a/data/mods/TEST_DATA/relics.json +++ b/data/mods/TEST_DATA/relics.json @@ -174,5 +174,29 @@ "relic_data": { "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "ITEM_DAMAGE_BASH", "multiply": -0.5, "add": 1 } ] } ] } + }, + { + "type": "GENERIC", + "id": "test_relic_item_armor_mod", + "copy-from": "test_hazmat_suit", + "name": "TEST relic item armor mod", + "relic_data": { + "passive_effects": [ + { "has": "WORN", "condition": "ALWAYS", "values": [ { "value": "ITEM_ARMOR_CUT", "multiply": -0.5, "add": 3 } ] }, + { "has": "WORN", "condition": "ALWAYS", "values": [ { "value": "ITEM_ARMOR_BASH", "multiply": 0.5, "add": -3 } ] } + ] + } + }, + { + "type": "GENERIC", + "id": "test_relic_char_armor_mod", + "copy-from": "test_socks", + "name": "TEST relic character armor mod", + "relic_data": { + "passive_effects": [ + { "has": "WORN", "condition": "ALWAYS", "values": [ { "value": "ARMOR_CUT", "multiply": -0.5, "add": -2 } ] }, + { "has": "WORN", "condition": "ALWAYS", "values": [ { "value": "ARMOR_STAB", "multiply": -0.1, "add": -3 } ] } + ] + } } ] diff --git a/tests/enchantment_test.cpp b/tests/enchantment_test.cpp index ce4a482c5ca7..1b5bd5f7073f 100644 --- a/tests/enchantment_test.cpp +++ b/tests/enchantment_test.cpp @@ -26,6 +26,14 @@ static item &give_item( Character &guy, const std::string &item_id ) return ret; } +static item &wear_item( Character &guy, const std::string &item_id ) +{ + item &ret = guy.i_add( item( item_id ) ); + guy.wear_item( ret, false ); + guy.recalculate_enchantment_cache(); + return ret; +} + static void clear_items( Character &guy ) { guy.inv.clear(); @@ -881,3 +889,58 @@ TEST_CASE( "Item enchantments modify item damage", "[magic][enchantment]" ) CHECK( impr.damage_melee( damage_type::DT_BASH ) == 11 ); } } + +static int calc_damage_absorb( Character &guy, damage_type dt, int amount ) +{ + static const bodypart_id torso( "torso" ); + damage_instance dmg( dt, amount ); + guy.absorb_hit( torso, dmg ); + assert( dmg.damage_units.size() == 1 ); + return amount - dmg.damage_units[0].amount; +} + +TEST_CASE( "Armor enchantments", "[magic][enchantment][armor]" ) +{ + clear_all_state(); + Character &guy = get_player_character(); + clear_character( *guy.as_player(), true ); + + REQUIRE( calc_damage_absorb( guy, damage_type::DT_CUT, 10 ) == 0 ); + REQUIRE( calc_damage_absorb( guy, damage_type::DT_BASH, 10 ) == 0 ); + REQUIRE( calc_damage_absorb( guy, damage_type::DT_STAB, 10 ) == 0 ); + + SECTION( "Armor item with no enchantments" ) { + wear_item( guy, "test_hazmat_suit" ); + + // 10 (incoming) - 4 (base item cut armor) = 6 (4 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_CUT, 10 ) == 4 ); + // 10 (incoming) - 4 (base item bash armor) = 6 (4 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_BASH, 10 ) == 4 ); + // 10 (incoming) - 3 (base item stab armor) = 7 (3 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_STAB, 10 ) == 3 ); + } + + SECTION( "Armor item with enchantment that trades bash armor for cut armor" ) { + wear_item( guy, "test_relic_item_armor_mod" ); + + // 10 (incoming) + (10 * -0.5 + 3) (enchantment) - 4 (base item cut armor) = 4 (6 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_CUT, 10 ) == 6 ); + // 10 (incoming) + (10 * 0.5 - 3) (enchantment) - 4 (base item bash armor) = 8 (2 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_BASH, 10 ) == 2 ); + // 10 (incoming) - 3 (base item stab armor) = 7 (3 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_STAB, 10 ) == 3 ); + } + + SECTION( "Armor item with no enchantments + socks of protection" ) { + wear_item( guy, "test_hazmat_suit" ); + // The socks provide character-wide protection regardless of what body parts they cover + wear_item( guy, "test_relic_char_armor_mod" ); + + // 10 (incoming) + (10 * -0.5 - 2) (enchantment) - 4 (base item cut armor) = -1 (10 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_CUT, 10 ) == 10 ); + // 10 (incoming) - 4 (base item bash armor) = 6 (4 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_BASH, 10 ) == 4 ); + // 10 (incoming) + (10 * -0.1 - 3) (enchantment) - 3 (base item stab armor) = 3 (7 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_STAB, 10 ) == 7 ); + } +} From b94fe42ad64ee2d68f5303cf8cc98ee583b76a34 Mon Sep 17 00:00:00 2001 From: Olanti Date: Sat, 31 Dec 2022 02:48:42 +0300 Subject: [PATCH 16/20] Style JSON --- data/mods/TEST_DATA/relics.json | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/data/mods/TEST_DATA/relics.json b/data/mods/TEST_DATA/relics.json index 27fbb4390acd..50f4b17d35ef 100644 --- a/data/mods/TEST_DATA/relics.json +++ b/data/mods/TEST_DATA/relics.json @@ -144,9 +144,7 @@ "id": "test_relic_mods_dodges", "copy-from": "test_relic_base", "name": "TEST relic mods dodges", - "relic_data": { - "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "BONUS_DODGE", "add": 1 } ] } ] - } + "relic_data": { "passive_effects": [ { "has": "HELD", "condition": "ALWAYS", "values": [ { "value": "BONUS_DODGE", "add": 1 } ] } ] } }, { "type": "GENERIC", @@ -183,7 +181,11 @@ "relic_data": { "passive_effects": [ { "has": "WORN", "condition": "ALWAYS", "values": [ { "value": "ITEM_ARMOR_CUT", "multiply": -0.5, "add": 3 } ] }, - { "has": "WORN", "condition": "ALWAYS", "values": [ { "value": "ITEM_ARMOR_BASH", "multiply": 0.5, "add": -3 } ] } + { + "has": "WORN", + "condition": "ALWAYS", + "values": [ { "value": "ITEM_ARMOR_BASH", "multiply": 0.5, "add": -3 } ] + } ] } }, From 6837cd6036ab0e0cfd61fc057b2be207d2314689 Mon Sep 17 00:00:00 2001 From: Olanti Date: Sat, 31 Dec 2022 03:14:20 +0300 Subject: [PATCH 17/20] Reset enchantment cache and dodges_left in clear_character() --- tests/enchantment_test.cpp | 16 ---------------- tests/player_helpers.cpp | 3 +++ 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/tests/enchantment_test.cpp b/tests/enchantment_test.cpp index 1b5bd5f7073f..d81787b92849 100644 --- a/tests/enchantment_test.cpp +++ b/tests/enchantment_test.cpp @@ -46,7 +46,6 @@ TEST_CASE( "Enchantments grant mutations", "[magic][enchantment][trait][mutation Character &guy = get_player_character(); clear_character( *guy.as_player(), true ); - guy.recalculate_enchantment_cache(); advance_turn( guy ); std::string s_relic = "test_relic_gives_trait"; @@ -115,7 +114,6 @@ TEST_CASE( "Enchantments apply effects", "[magic][enchantment][effect]" ) Character &guy = get_player_character(); clear_character( *guy.as_player(), true ); - guy.recalculate_enchantment_cache(); advance_turn( guy ); std::string s_relic = "architect_cube"; @@ -167,7 +165,6 @@ static void tests_stats( Character &guy, int s_base, int d_base, int p_base, int guy.per_max = p_base; guy.int_max = i_base; - guy.recalculate_enchantment_cache(); advance_turn( guy ); auto check_stats = [&]( int s, int d, int p, int i ) { @@ -234,7 +231,6 @@ TEST_CASE( "Enchantments modify stats", "[magic][enchantment][character]" ) static void tests_speed( Character &guy, int sp_base, int sp_exp ) { - guy.recalculate_enchantment_cache(); guy.set_speed_base( sp_base ); guy.set_speed_bonus( 0 ); @@ -320,7 +316,6 @@ TEST_CASE( "Enchantments modify speed", "[magic][enchantment][speed]" ) static void tests_attack_cost( Character &guy, const item &weap, int item_atk_cost, int guy_atk_cost, int exp_guy_atk_cost ) { - guy.recalculate_enchantment_cache(); advance_turn( guy ); REQUIRE( weap.attack_cost() == item_atk_cost ); @@ -366,7 +361,6 @@ TEST_CASE( "Enchantments modify attack cost", "[magic][enchantment][melee]" ) static void tests_move_cost( Character &guy, int tile_move_cost, int move_cost, int exp_move_cost ) { - guy.recalculate_enchantment_cache(); advance_turn( guy ); std::string s_relic = "test_relic_mods_mv_cost"; @@ -425,7 +419,6 @@ TEST_CASE( "Enchantments modify move cost", "[magic][enchantment][move]" ) static void tests_metabolic_rate( Character &guy, float norm, float exp ) { - guy.recalculate_enchantment_cache(); advance_turn( guy ); std::string s_relic = "test_relic_mods_metabolism"; @@ -460,7 +453,6 @@ TEST_CASE( "Enchantments modify metabolic rate", "[magic][enchantment][metabolis Character &guy = get_player_character(); clear_character( *guy.as_player(), true ); - guy.recalculate_enchantment_cache(); advance_turn( guy ); const float normal_mr = get_option( "PLAYER_HUNGER_RATE" ); @@ -504,7 +496,6 @@ static void tests_mana_pool( Character &guy, const mana_test_case &t ) double norm_regen_rate = t.norm_regen_amt_8h / to_turns( time_duration::from_hours( 8 ) ); double exp_regen_rate = t.exp_regen_amt_8h / to_turns( time_duration::from_hours( 8 ) ); - guy.recalculate_enchantment_cache(); advance_turn( guy ); guy.set_max_power_level( 2000_kJ ); @@ -587,7 +578,6 @@ static void tests_stamina( Character &guy, float rate_norm, float rate_exp ) { - guy.recalculate_enchantment_cache(); advance_turn( guy ); std::string s_relic = "test_relic_mods_stamina"; @@ -636,7 +626,6 @@ TEST_CASE( "Enchantments modify stamina", "[magic][enchantment][stamina]" ) Character &guy = get_player_character(); clear_character( *guy.as_player(), true ); - guy.recalculate_enchantment_cache(); advance_turn( guy ); REQUIRE( guy.get_stim() == 0 ); @@ -688,7 +677,6 @@ template static void tests_need_rate( Character &guy, const std::string &s_relic, float norm, float exp, F getter ) { - guy.recalculate_enchantment_cache(); advance_turn( guy ); REQUIRE( getter( guy ) == Approx( norm ) ); @@ -721,7 +709,6 @@ TEST_CASE( "Enchantments modify thirst rate", "[magic][enchantment][thirst]" ) Character &guy = get_player_character(); clear_character( *guy.as_player(), true ); - guy.recalculate_enchantment_cache(); advance_turn( guy ); std::string s_relic = "test_relic_mods_thirst"; @@ -751,7 +738,6 @@ TEST_CASE( "Enchantments modify fatigue rate", "[magic][enchantment][fatigue]" ) Character &guy = get_player_character(); clear_character( *guy.as_player(), true ); - guy.recalculate_enchantment_cache(); advance_turn( guy ); std::string s_relic = "test_relic_mods_fatigue"; @@ -783,8 +769,6 @@ static void check_num_dodges( const Character &guy, int num ) static void tests_num_dodges( Character &guy ) { - guy.recalculate_enchantment_cache(); - // Must have some moves to gain dodges guy.moves = 1; guy.dodges_left = 0; diff --git a/tests/player_helpers.cpp b/tests/player_helpers.cpp index 06f0d5911bdf..2521193611fd 100644 --- a/tests/player_helpers.cpp +++ b/tests/player_helpers.cpp @@ -73,6 +73,8 @@ void clear_character( player &dummy, bool debug_storage ) dummy.set_power_level( 0_J ); dummy.set_max_power_level( 0_J ); + dummy.recalculate_enchantment_cache(); + // Clear stomach and then eat a nutritious meal to normalize stomach // contents (needs to happen before clear_morale). dummy.stomach.empty(); @@ -115,6 +117,7 @@ void clear_character( player &dummy, bool debug_storage ) dummy.set_all_parts_hp_to_max(); dummy.cash = 0; + dummy.dodges_left = 1; const tripoint spot( 60, 60, 0 ); dummy.setpos( spot ); From cd0f9e3128934e0aadf8b0a0909b011a33822152 Mon Sep 17 00:00:00 2001 From: Olanti Date: Sat, 31 Dec 2022 14:18:20 +0300 Subject: [PATCH 18/20] Don't measure damaged clothing --- tests/enchantment_test.cpp | 54 +++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/tests/enchantment_test.cpp b/tests/enchantment_test.cpp index d81787b92849..1612a592542c 100644 --- a/tests/enchantment_test.cpp +++ b/tests/enchantment_test.cpp @@ -896,23 +896,35 @@ TEST_CASE( "Armor enchantments", "[magic][enchantment][armor]" ) SECTION( "Armor item with no enchantments" ) { wear_item( guy, "test_hazmat_suit" ); - // 10 (incoming) - 4 (base item cut armor) = 6 (4 absorbed) - CHECK( calc_damage_absorb( guy, damage_type::DT_CUT, 10 ) == 4 ); - // 10 (incoming) - 4 (base item bash armor) = 6 (4 absorbed) - CHECK( calc_damage_absorb( guy, damage_type::DT_BASH, 10 ) == 4 ); - // 10 (incoming) - 3 (base item stab armor) = 7 (3 absorbed) - CHECK( calc_damage_absorb( guy, damage_type::DT_STAB, 10 ) == 3 ); + SECTION( "Cut" ) { + // 10 (incoming) - 4 (base item cut armor) = 6 (4 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_CUT, 10 ) == 4 ); + } + SECTION( "Bash" ) { + // 10 (incoming) - 4 (base item bash armor) = 6 (4 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_BASH, 10 ) == 4 ); + } + SECTION( "Stab" ) { + // 10 (incoming) - 3 (base item stab armor) = 7 (3 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_STAB, 10 ) == 3 ); + } } SECTION( "Armor item with enchantment that trades bash armor for cut armor" ) { wear_item( guy, "test_relic_item_armor_mod" ); - // 10 (incoming) + (10 * -0.5 + 3) (enchantment) - 4 (base item cut armor) = 4 (6 absorbed) - CHECK( calc_damage_absorb( guy, damage_type::DT_CUT, 10 ) == 6 ); - // 10 (incoming) + (10 * 0.5 - 3) (enchantment) - 4 (base item bash armor) = 8 (2 absorbed) - CHECK( calc_damage_absorb( guy, damage_type::DT_BASH, 10 ) == 2 ); - // 10 (incoming) - 3 (base item stab armor) = 7 (3 absorbed) - CHECK( calc_damage_absorb( guy, damage_type::DT_STAB, 10 ) == 3 ); + SECTION( "Cut" ) { + // 10 (incoming) + (10 * -0.5 + 3) (enchantment) - 4 (base item cut armor) = 4 (6 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_CUT, 10 ) == 6 ); + } + SECTION( "Bash" ) { + // 10 (incoming) + (10 * 0.5 - 3) (enchantment) - 4 (base item bash armor) = 8 (2 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_BASH, 10 ) == 2 ); + } + SECTION( "Stab" ) { + // 10 (incoming) - 3 (base item stab armor) = 7 (3 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_STAB, 10 ) == 3 ); + } } SECTION( "Armor item with no enchantments + socks of protection" ) { @@ -920,11 +932,17 @@ TEST_CASE( "Armor enchantments", "[magic][enchantment][armor]" ) // The socks provide character-wide protection regardless of what body parts they cover wear_item( guy, "test_relic_char_armor_mod" ); - // 10 (incoming) + (10 * -0.5 - 2) (enchantment) - 4 (base item cut armor) = -1 (10 absorbed) - CHECK( calc_damage_absorb( guy, damage_type::DT_CUT, 10 ) == 10 ); - // 10 (incoming) - 4 (base item bash armor) = 6 (4 absorbed) - CHECK( calc_damage_absorb( guy, damage_type::DT_BASH, 10 ) == 4 ); - // 10 (incoming) + (10 * -0.1 - 3) (enchantment) - 3 (base item stab armor) = 3 (7 absorbed) - CHECK( calc_damage_absorb( guy, damage_type::DT_STAB, 10 ) == 7 ); + SECTION( "Cut" ) { + // 10 (incoming) + (10 * -0.5 - 2) (enchantment) - 4 (base item cut armor) = -1 (10 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_CUT, 10 ) == 10 ); + } + SECTION( "Bash" ) { + // 10 (incoming) - 4 (base item bash armor) = 6 (4 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_BASH, 10 ) == 4 ); + } + SECTION( "Stab" ) { + // 10 (incoming) + (10 * -0.1 - 3) (enchantment) - 3 (base item stab armor) = 3 (7 absorbed) + CHECK( calc_damage_absorb( guy, damage_type::DT_STAB, 10 ) == 7 ); + } } } From 5c267fe28b60bb4f74f8d3822a010666bf406429 Mon Sep 17 00:00:00 2001 From: Olanti Date: Sat, 31 Dec 2022 14:19:34 +0300 Subject: [PATCH 19/20] Clarify doc --- doc/MAGIC.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/MAGIC.md b/doc/MAGIC.md index ba00f9381ff9..225a2cb8b09f 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -475,8 +475,8 @@ This modifier ignores `add` field. The final value cannot go below 0. ##### BONUS_DODGE -Dodges per turn. -`base_value` here is character's base dodges per turn. +Additional dodges per turn before dodge penalty kicks in. +`base_value` here is character's base dodges per turn before penalty (usually 1). The final value can go below 0, which results in penalty to dodge roll. ##### ARMOR_X From 6b9da84271201dddd15ca585cccc615e7bec9c1b Mon Sep 17 00:00:00 2001 From: Olanti Date: Sat, 31 Dec 2022 14:44:09 +0300 Subject: [PATCH 20/20] Update enchant vals in Magiclysm --- data/mods/Magiclysm/items/bionics.json | 2 +- data/mods/Magiclysm/items/enchanted.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/mods/Magiclysm/items/bionics.json b/data/mods/Magiclysm/items/bionics.json index 163b2b6ca2c0..bc4738dafe17 100644 --- a/data/mods/Magiclysm/items/bionics.json +++ b/data/mods/Magiclysm/items/bionics.json @@ -12,7 +12,7 @@ { "type": "enchantment", "id": "ench_bio_sneeze_beam", - "values": [ { "value": "MAX_MANA", "add": 500 } ] + "values": [ { "value": "MANA_CAP", "add": 500 } ] }, { "id": "bio_sneeze_beam", diff --git a/data/mods/Magiclysm/items/enchanted.json b/data/mods/Magiclysm/items/enchanted.json index 5b353bdbb637..37951145520c 100644 --- a/data/mods/Magiclysm/items/enchanted.json +++ b/data/mods/Magiclysm/items/enchanted.json @@ -26,7 +26,7 @@ "material": "wood", "flags": [ "SHEATH_SPEAR", "ALWAYS_TWOHAND", "FRAGILE_MELEE", "MAGIC_FOCUS" ], "relic_data": { - "passive_effects": [ { "has": "WIELD", "condition": "ALWAYS", "values": [ { "value": "MAX_MANA", "multiply": 0.2, "add": 750 } ] } ] + "passive_effects": [ { "has": "WIELD", "condition": "ALWAYS", "values": [ { "value": "MANA_CAP", "multiply": 0.2, "add": 750 } ] } ] }, "weight": "1400 g", "volume": "3 L", @@ -52,7 +52,7 @@ "material_thickness": 2, "environmental_protection": 2, "relic_data": { - "passive_effects": [ { "has": "WORN", "condition": "ALWAYS", "values": [ { "value": "REGEN_MANA", "multiply": 1 } ] } ] + "passive_effects": [ { "has": "WORN", "condition": "ALWAYS", "values": [ { "value": "MANA_REGEN", "multiply": 1 } ] } ] }, "flags": [ "VARSIZE" ] },