From 4fd3179a2fc93a0b2896d5c01b496c8d58b720d5 Mon Sep 17 00:00:00 2001 From: Venera3 Date: Fri, 15 Mar 2024 16:32:04 +0100 Subject: [PATCH 1/3] Drying_rate --- doc/JSON_INFO.md | 3 +-- src/bodypart.cpp | 3 +-- src/bodypart.h | 3 +-- src/character_body.cpp | 7 +++---- tests/limb_test.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 10 deletions(-) diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index 746c8ec686dee..416284960b436 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -1051,8 +1051,7 @@ reference at least one body part or sub body part. | `hit_difficulty` | (_mandatory_) How hard is it to hit a given body part, assuming "owner" is hit. Higher number means good hits will veer towards this part, lower means this part is unlikely to be hit by inaccurate attacks. Formula is `chance *= pow(hit_roll, hit_difficulty)` | `drench_capacity` | (_mandatory_) How wet this part can get before being 100% drenched. 0 makes the limb waterproof, morale checks for absolute wetness while other effects for wetness percentage - making a high `drench_capacity` prevent the penalties longer. | `drench_increment` | (_optional_) Units of "wetness" applied each time the limb gets drenched. Default 2, ignored by diving underwater. -| `drying_chance` | (_optional_) Base chance the bodypart will succeed in the drying roll ( `x/80` chance, modified by ambient temperature etc) -| `drying_increment` | (_optonal_) Units of wetness the limb will dry each turn, if it succeeds in the drying roll (base chance `drench_capacity / 80`, modified by ambient temperature). +| `drying_rate` | (_optional float_) Divisor on the time needed to dry a given amount of wetness from a bodypart, modified by clothing. Final drying rate depends on breathability, weather, and `drying_capacity` of the bodypart. | `wet_morale` | (_optional_) Mood bonus/malus when the limb gets wet, representing the morale effect at 100% limb saturation. Modified by worn clothing and ambient temperature. | `stylish_bonus` | (_optional_) Mood bonus associated with wearing fancy clothing on this part. (default: `0`) | `hot_morale_mod` | (_optional_) Mood effect of being too hot on this part. (default: `0`) diff --git a/src/bodypart.cpp b/src/bodypart.cpp index 6927c4240d356..bb7f90e5bdde8 100644 --- a/src/bodypart.cpp +++ b/src/bodypart.cpp @@ -312,8 +312,7 @@ void body_part_type::load( const JsonObject &jo, const std::string_view ) mandatory( jo, was_loaded, "drench_capacity", drench_max ); optional( jo, was_loaded, "drench_increment", drench_increment, 2 ); - optional( jo, was_loaded, "drying_chance", drying_chance, drench_max ); - optional( jo, was_loaded, "drying_increment", drying_increment, 1 ); + optional( jo, was_loaded, "drying_rate", drying_rate, 1.0f ); optional( jo, was_loaded, "wet_morale", wet_morale, 0 ); diff --git a/src/bodypart.h b/src/bodypart.h index ce53dd91eb667..ff447c5a9f5a3 100644 --- a/src/bodypart.h +++ b/src/bodypart.h @@ -312,8 +312,7 @@ struct body_part_type { units::temperature_delta temp_max = 0_C_delta; int drench_max = 0; int drench_increment = 2; - int drying_chance = 1; - int drying_increment = 1; + float drying_rate = 1.0f; // Wetness morale bonus/malus of the limb int wet_morale = 0; int technique_enc_limit = 50; diff --git a/src/character_body.cpp b/src/character_body.cpp index 6e24a03bf3ac5..d0ff1bba3c0a1 100644 --- a/src/character_body.cpp +++ b/src/character_body.cpp @@ -135,11 +135,10 @@ void Character::update_body_wetness( const w_point &weather ) // Make clothing slow down drying const float clothing_mult = worn.clothing_wetness_mult( bp ); - - const time_duration drying = bp->drying_increment * average_drying * trait_mult * weather_mult * + const float drying_rate = bp->drying_rate; + const time_duration drying = average_drying * trait_mult * weather_mult * temp_mult / clothing_mult; - const float turns_to_dry = to_turns( drying ); - + const float turns_to_dry = to_turns( drying ) / drying_rate; const int drench_cap = get_part_drench_capacity( bp ); const float dry_per_turn = static_cast( drench_cap ) / turns_to_dry; mod_part_wetness( bp, roll_remainder( dry_per_turn ) * -1 ); diff --git a/tests/limb_test.cpp b/tests/limb_test.cpp index 6abde186199ff..6834cf1e9d578 100644 --- a/tests/limb_test.cpp +++ b/tests/limb_test.cpp @@ -144,6 +144,51 @@ TEST_CASE( "Healing/mending_bonuses", "[character][limb]" ) } } +TEST_CASE( "drying_rate", "[character][limb]" ) +{ + standard_npc dude( "Test NPC" ); + clear_character( dude, true ); + const weather_manager weather = get_weather(); + REQUIRE( body_part_arm_l->drying_rate == 1.0f ); + dude.drench( 100, dude.get_drenching_body_parts(), false ); + REQUIRE( dude.get_part_wetness( body_part_arm_l ) == 200 ); + + // Baseline arm dries in 450ish turns + int base_dry = 0; + while( dude.get_part_wetness( body_part_arm_l ) > 0 ) { + dude.update_body_wetness( *weather.weather_precise ); + base_dry++; + } + REQUIRE( base_dry == Approx( 450 ).margin( 100 ) ); + + // Birdify, clear water + clear_character( dude, true ); + create_bird_char( dude ); + REQUIRE( body_part_test_bird_wing_l->drying_rate == 2.0f ); + REQUIRE( body_part_test_bird_wing_r->drying_rate == 0.5f ); + REQUIRE( dude.get_part_wetness( body_part_test_bird_wing_l ) == 0 ); + REQUIRE( dude.get_part_wetness( body_part_test_bird_wing_r ) == 0 ); + dude.drench( 100, dude.get_drenching_body_parts(), false ); + REQUIRE( dude.get_part_wetness( body_part_test_bird_wing_l ) == 200 ); + REQUIRE( dude.get_part_wetness( body_part_test_bird_wing_r ) == 200 ); + + int high_dry = 0; + int low_dry = 0; + // Filter on the slower drying limb + while( dude.get_part_wetness( body_part_test_bird_wing_r ) > 0 ) { + dude.update_body_wetness( *weather.weather_precise ); + if( dude.get_part_wetness( body_part_test_bird_wing_l ) > 0 ) { + high_dry++; + } + low_dry++; + } + + // A drying rate of 2 should halve the drying time + // Higher margin for the lower rate to account for the randomness + CHECK( high_dry == Approx( base_dry / 2 ).margin( base_dry / 4 ) ); + CHECK( low_dry == Approx( base_dry * 2 ).margin( base_dry ) ); +} + TEST_CASE( "Limb_armor_coverage", "[character][limb][armor]" ) { standard_npc dude( "Test NPC" ); From e7183a5957ab21f4dbdc2abc51d98572427329ff Mon Sep 17 00:00:00 2001 From: Venera3 Date: Fri, 15 Mar 2024 20:03:41 +0100 Subject: [PATCH 2/3] Derp --- data/mods/TEST_DATA/body_parts.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/data/mods/TEST_DATA/body_parts.json b/data/mods/TEST_DATA/body_parts.json index 0b4934c95d080..f16e14b5e573d 100644 --- a/data/mods/TEST_DATA/body_parts.json +++ b/data/mods/TEST_DATA/body_parts.json @@ -148,11 +148,12 @@ "side": "left", "hot_morale_mod": 0.5, "cold_morale_mod": 0.5, + "drying_rate": 2, "fire_warmth_bonus": 600, "squeamish_penalty": 5, "is_limb": true, "base_hp": 60, - "drench_capacity": 10, + "drench_capacity": 1000, "smash_message": "You elbow-smash the %s.", "bionic_slots": 20, "ugliness": 30, @@ -208,7 +209,8 @@ "squeamish_penalty": 5, "is_limb": true, "base_hp": 60, - "drench_capacity": 10, + "drench_capacity": 1000, + "drying_rate": 0.5, "smash_message": "You elbow-smash the %s.", "bionic_slots": 20, "ugliness": 30, From 805d84f266cc5592c9d04571e1971e8d3369d939 Mon Sep 17 00:00:00 2001 From: I-am-Erk <45136638+I-am-Erk@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:15:40 -0700 Subject: [PATCH 3/3] Update doc/JSON_INFO.md --- doc/JSON_INFO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index 416284960b436..59a104079bc5b 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -1051,7 +1051,7 @@ reference at least one body part or sub body part. | `hit_difficulty` | (_mandatory_) How hard is it to hit a given body part, assuming "owner" is hit. Higher number means good hits will veer towards this part, lower means this part is unlikely to be hit by inaccurate attacks. Formula is `chance *= pow(hit_roll, hit_difficulty)` | `drench_capacity` | (_mandatory_) How wet this part can get before being 100% drenched. 0 makes the limb waterproof, morale checks for absolute wetness while other effects for wetness percentage - making a high `drench_capacity` prevent the penalties longer. | `drench_increment` | (_optional_) Units of "wetness" applied each time the limb gets drenched. Default 2, ignored by diving underwater. -| `drying_rate` | (_optional float_) Divisor on the time needed to dry a given amount of wetness from a bodypart, modified by clothing. Final drying rate depends on breathability, weather, and `drying_capacity` of the bodypart. +| `drying_rate` | (_optional float_) Divisor on the time needed to dry a given amount of wetness from a bodypart, modified by clothing. Final drying rate depends on breathability, weather, and `drying_capacity` of the bodypart. | `wet_morale` | (_optional_) Mood bonus/malus when the limb gets wet, representing the morale effect at 100% limb saturation. Modified by worn clothing and ambient temperature. | `stylish_bonus` | (_optional_) Mood bonus associated with wearing fancy clothing on this part. (default: `0`) | `hot_morale_mod` | (_optional_) Mood effect of being too hot on this part. (default: `0`)