From 831f14af4323076e58dfbb1bac6ea3a8068ece2c Mon Sep 17 00:00:00 2001 From: inogenous <123803852+inogenous@users.noreply.github.com> Date: Mon, 11 Nov 2024 23:31:11 +0100 Subject: [PATCH] Fix: Show consistent healing quality Fixes an issue where healing qualities shown when applying a bandage was different than the applied quality. The problem before was: * For example, applying an adhesive bandage with "wound care" proficiency should give bandaging intensity 2, as returned from `get_bandaged_level` - this is correct. * The `bandaged` effect as defined in `effects.json` specifies `int_dur_factor=6h`, so the intensity of this effect should be defined by setting its duration as multiples of `int_dur_factor`. * When calculating the duration for the created effect, the code previously added `0.5f` to the desired intensity, likely to prevent it from getting 0. <- This was one part of the previous problem. * In `effect::set_duration`, the intensity is calculated from how many multiples of `int_dur_factor` that the desired `duration` is. That calulation added 1 to the desired intensity, likely to also prevent it from being 0. <- This was the second problem before. * In effect, instead of applying intensity 2 for an adhesive bandage, the code previously applied intensity 3.5 . With this commit, we instead use `std::max(1, intensity)` to prevent intensity from being 0. --- src/creature.cpp | 4 ++-- src/effect.cpp | 4 ++-- src/iuse_actor.cpp | 8 ++++---- tests/effect_test.cpp | 18 +++++++++++++----- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/creature.cpp b/src/creature.cpp index ad5bd25cb4c4a..2f1223cb13b71 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -1759,8 +1759,8 @@ void Creature::add_effect( const effect_source &source, const efftype_id &eff_id // Force intensity if it is duration based if( e.get_int_dur_factor() != 0_turns ) { - // + 1 here so that the lowest is intensity 1, not 0 - e.set_intensity( e.get_duration() / e.get_int_dur_factor() + 1 ); + const int intensity = std::ceil( e.get_duration() / e.get_int_dur_factor() ); + e.set_intensity( std::max( 1, intensity ) ); } // Bound new effect intensity by [1, max intensity] if( e.get_intensity() < 1 ) { diff --git a/src/effect.cpp b/src/effect.cpp index a2181aa3dd748..56d792c769ce7 100644 --- a/src/effect.cpp +++ b/src/effect.cpp @@ -1083,8 +1083,8 @@ void effect::set_duration( const time_duration &dur, bool alert ) // Force intensity if it is duration based if( eff_type->int_dur_factor != 0_turns ) { - // + 1 here so that the lowest is intensity 1, not 0 - set_intensity( duration / eff_type->int_dur_factor + 1, alert ); + const int intensity = std::ceil( duration / eff_type->int_dur_factor ); + set_intensity( std::max( 1, intensity ), alert ); } add_msg_debug( debugmode::DF_EFFECT, "ID: %s, Duration %s", get_id().c_str(), diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 5a996d5f2060b..e9ded88cd96ce 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -3588,19 +3588,19 @@ int heal_actor::finish_using( Character &healer, Character &patient, item &it, // apply healing over time effects if( bandages_power > 0 ) { - int bandages_intensity = get_bandaged_level( healer ); + int bandages_intensity = std::max( 1, get_bandaged_level( healer ) ); patient.add_effect( effect_bandaged, 1_turns, healed ); effect &e = patient.get_effect( effect_bandaged, healed ); - e.set_duration( e.get_int_dur_factor() * ( bandages_intensity + 0.5f ) ); + e.set_duration( e.get_int_dur_factor() * bandages_intensity ); patient.set_part_damage_bandaged( healed, patient.get_part_hp_max( healed ) - patient.get_part_hp_cur( healed ) ); practice_amount += 2 * bandages_intensity; } if( disinfectant_power > 0 ) { - int disinfectant_intensity = get_disinfected_level( healer ); + int disinfectant_intensity = std::max( 1, get_disinfected_level( healer ) ); patient.add_effect( effect_disinfected, 1_turns, healed ); effect &e = patient.get_effect( effect_disinfected, healed ); - e.set_duration( e.get_int_dur_factor() * ( disinfectant_intensity + 0.5f ) ); + e.set_duration( e.get_int_dur_factor() * disinfectant_intensity ); patient.set_part_damage_disinfected( healed, patient.get_part_hp_max( healed ) - patient.get_part_hp_cur( healed ) ); practice_amount += 2 * disinfectant_intensity; diff --git a/tests/effect_test.cpp b/tests/effect_test.cpp index aba6c896e741d..d010d3eb6a601 100644 --- a/tests/effect_test.cpp +++ b/tests/effect_test.cpp @@ -111,12 +111,12 @@ TEST_CASE( "effect_duration", "[effect][duration]" ) // // "id": "drunk", // "name": [ "Tipsy", "Drunk", "Trashed", "Wasted" ], - // "max_intensity": 4, + // "max_intensity": 3, // "apply_message": "You feel lightheaded.", // "int_dur_factor": 1000, // // It has "int_dur_factor": 1000, meaning that its intensity will always be equal to its duration / - // 1000 rounded up, and it has "max_intensity": 4 meaning the highest its intensity will go is 4 at + // 1000 rounded up, and it has "max_intensity": 3 meaning the highest its intensity will go is 3 at // a duration of 3000 or higher. SECTION( "set_duration modifies intensity if effect is duration-based" ) { effect eff_intense( effect_source::empty(), &effect_intensified.obj(), 1_turns, body_part_bp_null, @@ -127,17 +127,25 @@ TEST_CASE( "effect_duration", "[effect][duration]" ) eff_intense.set_duration( 0_seconds ); CHECK( eff_intense.get_intensity() == 1 ); - // At duration == int_dur_factor, intensity is 2 + // At duration == int_dur_factor, intensity is 1 eff_intense.set_duration( 1_minutes ); - CHECK( eff_intense.get_intensity() == 2 ); + CHECK( eff_intense.get_intensity() == 1 ); - // At duration == 2 * int_dur_factor, intensity is 3 + // At duration == 2 * int_dur_factor, intensity is 2 eff_intense.set_duration( 2_minutes ); + CHECK( eff_intense.get_intensity() == 2 ); + + // At duration == (2m1s) * int_dur_factor, intensity is 3 (rounds up) + eff_intense.set_duration( 2_minutes + 1_seconds ); CHECK( eff_intense.get_intensity() == 3 ); // At duration == 3 * int_dur_factor, intensity is still 3 eff_intense.set_duration( 3_minutes ); CHECK( eff_intense.get_intensity() == 3 ); + + // At duration == 4 * int_dur_factor, intensity is still 3 + eff_intense.set_duration( 4_minutes ); + CHECK( eff_intense.get_intensity() == 3 ); } }