Skip to content

Commit

Permalink
Merge pull request #42430 from Fris0uman/wetcap
Browse files Browse the repository at this point in the history
Fix infinite wetness
  • Loading branch information
ZhilkinSerg authored Jul 28, 2020
2 parents bcc0b83 + cac7075 commit 0ae7066
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 88 deletions.
79 changes: 79 additions & 0 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,22 @@ static const trait_id trait_ADRENALINE( "ADRENALINE" );
static const trait_id trait_ANTENNAE( "ANTENNAE" );
static const trait_id trait_ANTLERS( "ANTLERS" );
static const trait_id trait_BADBACK( "BADBACK" );
static const trait_id trait_CHITIN_FUR( "CHITIN_FUR" );
static const trait_id trait_CHITIN_FUR2( "CHITIN_FUR2" );
static const trait_id trait_CHITIN_FUR3( "CHITIN_FUR3" );
static const trait_id trait_DEBUG_NODMG( "DEBUG_NODMG" );
static const trait_id trait_FELINE_FUR( "FELINE_FUR" );
static const trait_id trait_FUR( "FUR" );
static const trait_id trait_LIGHTFUR( "LIGHTFUR" );
static const trait_id trait_LUPINE_FUR( "LUPINE_FUR" );
static const trait_id trait_HUGE( "HUGE" );
static const trait_id trait_HUGE_OK( "HUGE_OK" );
static const trait_id trait_PACIFIST( "PACIFIST" );
static const trait_id trait_SAVANT( "SAVANT" );
static const trait_id trait_SMALL2( "SMALL2" );
static const trait_id trait_SMALL_OK( "SMALL_OK" );
static const trait_id trait_SQUEAMISH( "SQUEAMISH" );
static const trait_id trait_URSINE_FUR( "URSINE_FUR" );
static const trait_id trait_WOOLALLERGY( "WOOLALLERGY" );

static const bionic_id bio_ads( "bio_ads" );
Expand Down Expand Up @@ -1773,6 +1781,77 @@ int Character::get_part_hp_max( const bodypart_id &id ) const
return enchantment_cache.modify_value( enchant_vals::mod::MAX_HP, Creature::get_part_hp_max( id ) );
}

void Character::update_body_wetness( const w_point &weather )
{
// Average number of turns to go from completely soaked to fully dry
// assuming average temperature and humidity
constexpr time_duration average_drying = 2_hours;

// A modifier on drying time
double delay = 1.0;
// Weather slows down drying
delay += ( ( weather.humidity - 66 ) - ( weather.temperature - 65 ) ) / 100;
delay = std::max( 0.1, delay );
// Fur/slime retains moisture
if( has_trait( trait_LIGHTFUR ) || has_trait( trait_FUR ) || has_trait( trait_FELINE_FUR ) ||
has_trait( trait_LUPINE_FUR ) || has_trait( trait_CHITIN_FUR ) || has_trait( trait_CHITIN_FUR2 ) ||
has_trait( trait_CHITIN_FUR3 ) ) {
delay = delay * 6 / 5;
}
if( has_trait( trait_URSINE_FUR ) || has_trait( trait_SLIMY ) ) {
delay *= 1.5;
}

if( !x_in_y( 1, to_turns<int>( average_drying * delay / 100.0 ) ) ) {
// No drying this turn
return;
}

// Now per-body-part stuff
// To make drying uniform, make just one roll and reuse it
const int drying_roll = rng( 1, 80 );

for( const bodypart_id &bp : get_all_body_parts() ) {
if( get_part_wetness( bp ) == 0 ) {
continue;
}
// This is to normalize drying times
int drying_chance = get_part_drench_capacity( bp );
const int temp_conv = get_part_temp_conv( bp );
// Body temperature affects duration of wetness
// Note: Using temp_conv rather than temp_cur, to better approximate environment
if( temp_conv >= BODYTEMP_SCORCHING ) {
drying_chance *= 2;
} else if( temp_conv >= BODYTEMP_VERY_HOT ) {
drying_chance = drying_chance * 3 / 2;
} else if( temp_conv >= BODYTEMP_HOT ) {
drying_chance = drying_chance * 4 / 3;
} else if( temp_conv > BODYTEMP_COLD ) {
// Comfortable, doesn't need any changes
} else {
// Evaporation doesn't change that much at lower temp
drying_chance = drying_chance * 3 / 4;
}

if( drying_chance < 1 ) {
drying_chance = 1;
}

// TODO: Make evaporation reduce body heat
if( drying_chance >= drying_roll ) {
mod_part_wetness( bp, -1 );
if( get_part_wetness( bp ) < 0 ) {
set_part_wetness( bp, 0 );
}
}
// Safety measure to keep wetness within bounds
if( get_part_wetness( bp ) > get_part_drench_capacity( bp ) ) {
set_part_wetness( bp, get_part_drench_capacity( bp ) );
}
}
// TODO: Make clothing slow down drying
}

// This must be called when any of the following change:
// - effects
// - bionics
Expand Down
5 changes: 5 additions & 0 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "units.h"
#include "visitable.h"
#include "weighted_list.h"
#include "weather_gen.h"

class JsonIn;
class JsonObject;
Expand Down Expand Up @@ -637,6 +638,10 @@ class Character : public Creature, public visitable<Character>
* - underwater
* - clothes
*/

/** Maintains body wetness and handles the rate at which the player dries */
void update_body_wetness( const w_point &weather );

void recalc_sight_limits();
/**
* Returns the apparent light level at which the player can see.
Expand Down
4 changes: 4 additions & 0 deletions src/effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ enum effect_rating {
e_mixed // The effect has good and bad parts to the one who has it.
};

/** @relates string_id */
template<>
const effect_type &string_id<effect_type>::obj() const;

class effect_type
{
friend void load_effect_type( const JsonObject &jo );
Expand Down
2 changes: 1 addition & 1 deletion src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9873,7 +9873,7 @@ point game::place_player( const tripoint &dest_loc )
// Drench the player if swimmable
if( m.has_flag( "SWIMMABLE", u.pos() ) &&
!( u.is_mounted() || ( u.in_vehicle && vp1->vehicle().can_float() ) ) ) {
u.drench( 40, { { bodypart_str_id( "foot_l" ), bodypart_str_id( "foot_r" ), bodypart_str_id( "leg_l" ), bodypart_str_id( "leg_r" ) } },
u.drench( 80, { { bodypart_str_id( "foot_l" ), bodypart_str_id( "foot_r" ), bodypart_str_id( "leg_l" ), bodypart_str_id( "leg_r" ) } },
false );
}

Expand Down
2 changes: 1 addition & 1 deletion src/iuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5888,7 +5888,7 @@ int iuse::towel_common( Character *p, item *it, bool t )
}

// dry off from being wet
} else if( std::abs( p->has_morale( MORALE_WET ) ) ) {
} else if( p->has_atleast_one_wet_part() ) {
p->rem_morale( MORALE_WET );
p->set_all_parts_wetness( 0 );
p->add_msg_if_player( _( "You use the %s to dry off, saturating it with water!" ),
Expand Down
78 changes: 1 addition & 77 deletions src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,6 @@ static const trait_id trait_DEBUG_NODMG( "DEBUG_NODMG" );
static const trait_id trait_CANNIBAL( "CANNIBAL" );
static const trait_id trait_CENOBITE( "CENOBITE" );
static const trait_id trait_CF_HAIR( "CF_HAIR" );
static const trait_id trait_CHITIN_FUR( "CHITIN_FUR" );
static const trait_id trait_CHITIN_FUR2( "CHITIN_FUR2" );
static const trait_id trait_CHITIN_FUR3( "CHITIN_FUR3" );
static const trait_id trait_CHLOROMORPH( "CHLOROMORPH" );
static const trait_id trait_CLUMSY( "CLUMSY" );
static const trait_id trait_COLDBLOOD4( "COLDBLOOD4" );
Expand All @@ -138,8 +135,6 @@ static const trait_id trait_EASYSLEEPER( "EASYSLEEPER" );
static const trait_id trait_EASYSLEEPER2( "EASYSLEEPER2" );
static const trait_id trait_EATHEALTH( "EATHEALTH" );
static const trait_id trait_FAT( "FAT" );
static const trait_id trait_FELINE_FUR( "FELINE_FUR" );
static const trait_id trait_FUR( "FUR" );
static const trait_id trait_HATES_BOOKS( "HATES_BOOKS" );
static const trait_id trait_HUGE( "HUGE" );
static const trait_id trait_HUGE_OK( "HUGE_OK" );
Expand All @@ -148,10 +143,8 @@ static const trait_id trait_INSOMNIA( "INSOMNIA" );
static const trait_id trait_INT_SLIME( "INT_SLIME" );
static const trait_id trait_LARGE( "LARGE" );
static const trait_id trait_LARGE_OK( "LARGE_OK" );
static const trait_id trait_LIGHTFUR( "LIGHTFUR" );
static const trait_id trait_LIGHTSTEP( "LIGHTSTEP" );
static const trait_id trait_LOVES_BOOKS( "LOVES_BOOKS" );
static const trait_id trait_LUPINE_FUR( "LUPINE_FUR" );
static const trait_id trait_M_IMMUNE( "M_IMMUNE" );
static const trait_id trait_M_SKIN3( "M_SKIN3" );
static const trait_id trait_MORE_PAIN( "MORE_PAIN" );
Expand All @@ -174,14 +167,12 @@ static const trait_id trait_QUILLS( "QUILLS" );
static const trait_id trait_SAPIOVORE( "SAPIOVORE" );
static const trait_id trait_SAVANT( "SAVANT" );
static const trait_id trait_SHELL2( "SHELL2" );
static const trait_id trait_SLIMY( "SLIMY" );
static const trait_id trait_SPINES( "SPINES" );
static const trait_id trait_SPIRITUAL( "SPIRITUAL" );
static const trait_id trait_STRONGSTOMACH( "STRONGSTOMACH" );
static const trait_id trait_SUNLIGHT_DEPENDENT( "SUNLIGHT_DEPENDENT" );
static const trait_id trait_THORNS( "THORNS" );
static const trait_id trait_THRESH_SPIDER( "THRESH_SPIDER" );
static const trait_id trait_URSINE_FUR( "URSINE_FUR" );
static const trait_id trait_VOMITOUS( "VOMITOUS" );
static const trait_id trait_WATERSLEEP( "WATERSLEEP" );
static const trait_id trait_WEAKSTOMACH( "WEAKSTOMACH" );
Expand Down Expand Up @@ -774,7 +765,7 @@ void player::pause()
}
}, true );
} else if( here.has_flag( "SWIMMABLE", pos() ) ) {
drench( 40, { { bodypart_str_id( "foot_l" ), bodypart_str_id( "foot_r" ), bodypart_str_id( "leg_l" ), bodypart_str_id( "leg_r" ) } },
drench( 80, { { bodypart_str_id( "foot_l" ), bodypart_str_id( "foot_r" ), bodypart_str_id( "leg_l" ), bodypart_str_id( "leg_r" ) } },
false );
}
}
Expand Down Expand Up @@ -1722,73 +1713,6 @@ double player::vomit_mod()
return mod;
}

void player::update_body_wetness( const w_point &weather )
{
// Average number of turns to go from completely soaked to fully dry
// assuming average temperature and humidity
constexpr time_duration average_drying = 2_hours;

// A modifier on drying time
double delay = 1.0;
// Weather slows down drying
delay += ( ( weather.humidity - 66 ) - ( weather.temperature - 65 ) ) / 100;
delay = std::max( 0.1, delay );
// Fur/slime retains moisture
if( has_trait( trait_LIGHTFUR ) || has_trait( trait_FUR ) || has_trait( trait_FELINE_FUR ) ||
has_trait( trait_LUPINE_FUR ) || has_trait( trait_CHITIN_FUR ) || has_trait( trait_CHITIN_FUR2 ) ||
has_trait( trait_CHITIN_FUR3 ) ) {
delay = delay * 6 / 5;
}
if( has_trait( trait_URSINE_FUR ) || has_trait( trait_SLIMY ) ) {
delay *= 1.5;
}

if( !x_in_y( 1, to_turns<int>( average_drying * delay / 100.0 ) ) ) {
// No drying this turn
return;
}

// Now per-body-part stuff
// To make drying uniform, make just one roll and reuse it
const int drying_roll = rng( 1, 80 );

for( const bodypart_id &bp : get_all_body_parts() ) {
if( get_part_wetness( bp ) == 0 ) {
continue;
}
// This is to normalize drying times
int drying_chance = get_part_drench_capacity( bp );
const int temp_conv = get_part_temp_conv( bp );
// Body temperature affects duration of wetness
// Note: Using temp_conv rather than temp_cur, to better approximate environment
if( temp_conv >= BODYTEMP_SCORCHING ) {
drying_chance *= 2;
} else if( temp_conv >= BODYTEMP_VERY_HOT ) {
drying_chance = drying_chance * 3 / 2;
} else if( temp_conv >= BODYTEMP_HOT ) {
drying_chance = drying_chance * 4 / 3;
} else if( temp_conv > BODYTEMP_COLD ) {
// Comfortable, doesn't need any changes
} else {
// Evaporation doesn't change that much at lower temp
drying_chance = drying_chance * 3 / 4;
}

if( drying_chance < 1 ) {
drying_chance = 1;
}

// TODO: Make evaporation reduce body heat
if( drying_chance >= drying_roll ) {
mod_part_wetness( bp, 1 );
if( get_part_wetness( bp ) < 0 ) {
set_part_wetness( bp, 0 );
}
}
}
// TODO: Make clothing slow down drying
}

void player::on_worn_item_transform( const item &old_it, const item &new_it )
{
morale->on_worn_item_transform( old_it, new_it );
Expand Down
3 changes: 0 additions & 3 deletions src/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,6 @@ class player : public Character
/** Calculates the various speed bonuses we will get from mutations, etc. */
void recalc_speed_bonus();

/** Maintains body wetness and handles the rate at which the player dries */
void update_body_wetness( const w_point &weather );

/** Returns true if the player has a conflicting trait to the entered trait
* Uses has_opposite_trait(), has_lower_trait(), and has_higher_trait() to determine conflicts.
*/
Expand Down
4 changes: 2 additions & 2 deletions src/suffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1747,7 +1747,7 @@ void Character::drench( int saturation, const body_part_set &flags, bool ignore_
continue;
}
// Different sources will only make the bodypart wet to a limit
int source_wet_max = saturation * bp_wetness_max * 2 / 100;
int source_wet_max = saturation * bp_wetness_max / 100;
int wetness_increment = ignore_waterproof ? 100 : 2;
// Respect maximums
const int wetness_max = std::min( source_wet_max, bp_wetness_max );
Expand All @@ -1757,7 +1757,7 @@ void Character::drench( int saturation, const body_part_set &flags, bool ignore_
}
}
const int torso_wetness = get_part_wetness( bodypart_id( "torso" ) );
if( torso_wetness >= torso_wetness / 2.0 &&
if( torso_wetness >= get_part_drench_capacity( bodypart_id( "torso" ) ) / 2.0 &&
has_effect( effect_masked_scent ) &&
get_value( "waterproof_scent" ).empty() ) {
add_msg_if_player( m_info, _( "The water wash away the scent." ) );
Expand Down
6 changes: 2 additions & 4 deletions tests/iuse_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,6 @@ TEST_CASE( "towel", "[iuse][towel]" )
REQUIRE( dummy.get_part_wetness( bodypart_id( "arm_l" ) ) > 0 );
REQUIRE( dummy.get_part_wetness( bodypart_id( "arm_r" ) ) > 0 );

// FIXME: Morale alone is the trigger for drying off!
// Without the morale modifier, towel_common thinks you're dry
dummy.add_morale( MORALE_WET, -10, -10, 1_hours, 1_hours );

WHEN( "they use a dry towel" ) {
REQUIRE_FALSE( towel.has_flag( flag_WET ) );
dummy.invoke_item( &towel );
Expand Down Expand Up @@ -374,6 +370,8 @@ TEST_CASE( "towel", "[iuse][towel]" )
}

GIVEN( "avatar has poor morale due to being wet" ) {
dummy.drench( 100, { bodypart_str_id( "torso" ), bodypart_str_id( "head" ), bodypart_str_id( "arm_l" ), bodypart_str_id( "arm_r" ) },
false );
dummy.add_morale( MORALE_WET, -10, -10, 1_hours, 1_hours );
REQUIRE( dummy.has_morale( MORALE_WET ) == -10 );

Expand Down

0 comments on commit 0ae7066

Please sign in to comment.