Skip to content

Commit

Permalink
perspiration, wetness, evaporation
Browse files Browse the repository at this point in the history
  • Loading branch information
Robik81 committed Oct 18, 2020
1 parent 953a494 commit da6a01a
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 53 deletions.
24 changes: 12 additions & 12 deletions data/json/body_parts.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"fire_warmth_bonus": 150,
"squeamish_penalty": 6,
"base_hp": 60,
"drench_capacity": 40,
"drench_capacity": 4000,
"smash_message": "You smash the %s with a powerful shoulder-check.",
"bionic_slots": 80
},
Expand All @@ -49,7 +49,7 @@
"fire_warmth_bonus": 150,
"squeamish_penalty": 7,
"base_hp": 60,
"drench_capacity": 7,
"drench_capacity": 700,
"smash_message": "You smash the %s with a firm headbutt.",
"smash_efficiency": 0.25,
"bionic_slots": 18
Expand All @@ -72,7 +72,7 @@
"stylish_bonus": 2,
"squeamish_penalty": 8,
"base_hp": 60,
"drench_capacity": 1,
"drench_capacity": 100,
"flags": [ "IGNORE_TEMP" ],
"smash_message": "You use your flippin' face to smash the %s. EXTREME.",
"smash_efficiency": 0.25,
Expand All @@ -98,7 +98,7 @@
"cold_morale_mod": 2,
"squeamish_penalty": 9,
"base_hp": 60,
"drench_capacity": 1,
"drench_capacity": 100,
"smash_message": "You use your flippin' face to smash the %s. EXTREME.",
"smash_efficiency": 0.25,
"bionic_slots": 4
Expand Down Expand Up @@ -129,7 +129,7 @@
"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
},
Expand Down Expand Up @@ -158,7 +158,7 @@
"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
},
Expand All @@ -185,7 +185,7 @@
"fire_warmth_bonus": 1500,
"squeamish_penalty": 3,
"base_hp": 60,
"drench_capacity": 3,
"drench_capacity": 300,
"smash_message": "You smash the %s with your fist.",
"bionic_slots": 5
},
Expand All @@ -212,7 +212,7 @@
"fire_warmth_bonus": 1500,
"squeamish_penalty": 3,
"base_hp": 60,
"drench_capacity": 3,
"drench_capacity": 300,
"smash_message": "You smash the %s with your fist.",
"bionic_slots": 5
},
Expand Down Expand Up @@ -242,7 +242,7 @@
"squeamish_penalty": 5,
"is_limb": true,
"base_hp": 60,
"drench_capacity": 11,
"drench_capacity": 1100,
"smash_message": "You bring your knee down on the %s, smashing it.",
"bionic_slots": 30
},
Expand Down Expand Up @@ -272,7 +272,7 @@
"squeamish_penalty": 5,
"is_limb": true,
"base_hp": 60,
"drench_capacity": 11,
"drench_capacity": 1100,
"smash_message": "You bring your knee down on the %s, smashing it.",
"bionic_slots": 30
},
Expand All @@ -299,7 +299,7 @@
"fire_warmth_bonus": 300,
"squeamish_penalty": 3,
"base_hp": 60,
"drench_capacity": 3,
"drench_capacity": 300,
"smash_message": "You kick down the %s, smashing it.",
"bionic_slots": 7
},
Expand All @@ -326,7 +326,7 @@
"fire_warmth_bonus": 300,
"squeamish_penalty": 3,
"base_hp": 60,
"drench_capacity": 3,
"drench_capacity": 300,
"smash_message": "You kick down the %s, smashing it.",
"bionic_slots": 7
}
Expand Down
24 changes: 18 additions & 6 deletions data/json/effects.json
Original file line number Diff line number Diff line change
Expand Up @@ -1113,20 +1113,32 @@
"type": "effect_type",
"id": "hot",
"name": [ "Warm", "Hot", "Scorching" ],
"desc": [ "Your %s feels warm.", "Your %s is sweating from the heat.", "Your %s is sweating profusely!" ],
"desc": [ "Your %s feels warm and sweaty.", "Your %s is sweating a lot from the heat.", "Your %s is sweating profusely!" ],
"max_intensity": 3,
"part_descs": true,
"base_mods": {
"thirst_tick": [ 2400 ],
"thirst_chance": [ 2 ],
"thirst_min": [ 1 ],
"thirst_tick": [ 200 ],
"thirst_chance": [ 6 ],
"perspiration_min": [ 10 ],
"perspiration_tick": [ 60 ],
"perspiration_chance": [ 1 ],
"pain_min": [ 1 ],
"pain_chance": [ 2 ],
"pain_max_val": [ -1 ],
"hurt_min": [ 1 ],
"hurt_chance": [ -300 ],
"stamina_chance": [ 2 ]
},
"scaling_mods": { "thirst_min": [ 1 ], "thirst_tick": [ -600 ], "pain_max_val": [ 10 ], "hurt_chance": [ 200 ], "stamina_min": [ -1 ] }
"scaling_mods": {
"thirst_tick": [ -50 ],
"thirst_chance": [ -1 ],
"perspiration_min": [ 5 ],
"perspiration_tick": [ -15 ],
"pain_max_val": [ 10 ],
"hurt_chance": [ 200 ],
"stamina_min": [ -1 ]
}
},
{
"type": "effect_type",
Expand All @@ -1136,8 +1148,8 @@
"speed_name": "Heat slowdown",
"max_intensity": 3,
"part_descs": true,
"base_mods": { "speed_mod": [ -2 ] },
"scaling_mods": { "speed_mod": [ -4 ] }
"base_mods": { "speed_mod": [ -1 ] },
"scaling_mods": { "speed_mod": [ -2 ] }
},
{
"type": "effect_type",
Expand Down
9 changes: 9 additions & 0 deletions doc/EFFECTS_JSON.md
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,15 @@ Valid arguments:
"thirst_chance_bot"
"thirst_tick" - Defaults to every tick

"perspiration_amount" - Amount of perspiration it can give/take.
"perspiration_min" - Minimal amount of perspiration, certain effect will give/take
"perspiration_max" - if 0 or missing value will be exactly "perspiration_min"
"perspiration_min_val" - Defaults to 0, which means uncapped
"perspiration_max_val" - Defaults to 0, which means uncapped
"perspiration_chance" - Chance to perspire
"perspiration_chance_bot"
"perspiration_tick" - Defaults to every tick

"fatigue_amount" - Amount of fatigue it can give/take. After certain amount character will need to sleep.
"fatigue_min" - Minimal amount of fatigue, certain effect will give/take
"fatigue_max" - if 0 or missing value will be exactly "fatigue_min"
Expand Down
91 changes: 58 additions & 33 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1942,71 +1942,83 @@ 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;
constexpr time_duration average_drying = 30_minutes;

// 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
double trait_mult = 1.0;
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;
trait_mult = 2.0;
}
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;
trait_mult = 4.0;
}

// Now per-body-part stuff
// To make drying uniform, make just one roll and reuse it
const int drying_roll = rng( 1, 80 );
// Weather slows down drying
double weather_mult = 1.0;
weather_mult += ( ( weather.humidity - 66 ) - ( weather.temperature - 65 ) ) / 100;
weather_mult = std::max( 0.1, weather_mult );

for( const bodypart_id &bp : get_all_body_parts() ) {
if( get_part_wetness( bp ) == 0 ) {
const int wetness = get_part_wetness( bp );
if( wetness == 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
const int temp_conv = get_part_temp_conv( bp );
double temp_mult = 1.0;
if( temp_conv >= BODYTEMP_SCORCHING ) {
drying_chance *= 2;
temp_mult = 0.5;
} else if( temp_conv >= BODYTEMP_VERY_HOT ) {
drying_chance = drying_chance * 3 / 2;
temp_mult = 0.67;
} else if( temp_conv >= BODYTEMP_HOT ) {
drying_chance = drying_chance * 4 / 3;
temp_mult = 0.75 ;
} 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;
temp_mult = 1.2;
}

if( drying_chance < 1 ) {
drying_chance = 1;
}
// Make clothing slow down drying
double clothing_mult = 1.0;
for( const item &i : worn ) {
if( i.covers( bp ) ) {
const double item_coverage = static_cast<double>( i.get_coverage( bp ) ) / 100;
const double item_breathability = static_cast<double>( i.breathability() ) / 100;

// breathability of naked skin + breathability of item
const double breathability = ( 1.0 - item_coverage ) + item_coverage * item_breathability;

// 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 );
clothing_mult += 1.0 - breathability;
}
}

const time_duration drying = average_drying * trait_mult * weather_mult * temp_mult * clothing_mult;
const double turns_to_dry = to_turns<double>( drying );

const int drench_cap = get_part_drench_capacity( bp );
const double dry_per_turn = static_cast<double>( drench_cap ) / turns_to_dry;
mod_part_wetness( bp, roll_remainder( dry_per_turn ) * -1 );

// Make evaporation reduce body heat
if( !( bp->has_flag( "IGNORE_TEMP" ) ) ) {
const int temp_cur = get_part_temp_cur( bp );
mod_part_temp_cur( bp, roll_remainder( static_cast<double>( temp_cur ) / clothing_mult / 2000 ) *
-1 );
}

// Safety measure to keep wetness within bounds
if( get_part_wetness( bp ) < 0 ) {
set_part_wetness( bp, 0 );
}
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:
Expand Down Expand Up @@ -11906,6 +11918,19 @@ void Character::process_one_effect( effect &it, bool is_new )
}
}

// Handle perspiration
val = get_effect( "PERSPIRATION", reduced );
if( val != 0 ) {
mod = 1;
if( is_new || it.activated( calendar::turn, "PERSPIRATION", val, reduced, mod ) ) {
// multiplier to balance values aroud drench capacity of different body parts
int mult = get_part_drench_capacity( bp ) / 100;
mod_part_wetness( bp, bound_mod_to_vals( get_part_wetness( bp ), val * mult,
it.get_max_val( "PERSPIRATION", reduced ) * mult,
it.get_min_val( "PERSPIRATION", reduced ) * mult ) );
}
}

// Handle fatigue
val = get_effect( "FATIGUE", reduced );
// Prevent ongoing fatigue effects while asleep.
Expand Down
13 changes: 13 additions & 0 deletions src/effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,16 @@ bool effect_type::load_mod_data( const JsonObject &jo, const std::string &member
extract_effect( j, mod_data, "thirst_chance_bot", member, "THIRST", "chance_bot" );
extract_effect( j, mod_data, "thirst_tick", member, "THIRST", "tick" );

// Then thirst
extract_effect( j, mod_data, "perspiration_amount", member, "PERSPIRATION", "amount" );
extract_effect( j, mod_data, "perspiration_min", member, "PERSPIRATION", "min" );
extract_effect( j, mod_data, "perspiration_max", member, "PERSPIRATION", "max" );
extract_effect( j, mod_data, "perspiration_min_val", member, "PERSPIRATION", "min_val" );
extract_effect( j, mod_data, "perspiration_max_val", member, "PERSPIRATION", "max_val" );
extract_effect( j, mod_data, "perspiration_chance", member, "PERSPIRATION", "chance_top" );
extract_effect( j, mod_data, "perspiration_chance_bot", member, "PERSPIRATION", "chance_bot" );
extract_effect( j, mod_data, "perspiration_tick", member, "PERSPIRATION", "tick" );

// Then fatigue
extract_effect( j, mod_data, "fatigue_amount", member, "FATIGUE", "amount" );
extract_effect( j, mod_data, "fatigue_min", member, "FATIGUE", "min" );
Expand Down Expand Up @@ -647,6 +657,9 @@ std::string effect::disp_desc( bool reduced ) const
val = get_avg_mod( "THIRST", reduced );
values.push_back( desc_freq( get_percentage( "THIRST", val, reduced ), val, _( "thirst" ),
_( "quench" ) ) );
val = get_avg_mod( "PERSPIRATION", reduced );
values.push_back( desc_freq( get_percentage( "PERSPIRATION", val, reduced ), val,
_( "perspiration" ), _( "dryness" ) ) );
val = get_avg_mod( "HUNGER", reduced );
values.push_back( desc_freq( get_percentage( "HUNGER", val, reduced ), val, _( "hunger" ),
_( "sate" ) ) );
Expand Down
4 changes: 2 additions & 2 deletions src/suffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1905,7 +1905,7 @@ void Character::drench( int saturation, const body_part_set &flags, bool ignore_
const int wetness_max = std::min( source_wet_max, bp_wetness_max );
const int curr_wetness = get_part_wetness( bp );
if( curr_wetness < wetness_max ) {
set_part_wetness( bp, std::min( wetness_max, curr_wetness + wetness_increment ) );
set_part_wetness( bp, std::min( wetness_max, curr_wetness + wetness_increment * 100 ) );
}
}
const int torso_wetness = get_part_wetness( bodypart_id( "torso" ) );
Expand Down Expand Up @@ -1942,7 +1942,7 @@ void Character::apply_wetness_morale( int temperature )
const body_part_set wet_friendliness = exclusive_flag_coverage( "WATER_FRIENDLY" );
for( const bodypart_id &bp : get_all_body_parts() ) {
// Sum of body wetness can go up to 103
const int part_drench = get_part_wetness( bp );
const int part_drench = get_part_wetness( bp ) / 100;
if( part_drench == 0 ) {
continue;
}
Expand Down

0 comments on commit da6a01a

Please sign in to comment.