diff --git a/data/json/effects.json b/data/json/effects.json index b828afbdd879c..274348d9baaee 100644 --- a/data/json/effects.json +++ b/data/json/effects.json @@ -2643,8 +2643,9 @@ "id": "formication", "name": [ "Itchy Skin", "Writhing Skin", "Bugs in Skin" ], "desc": [ "You stop to scratch yourself frequently; high INT helps you resist the urge." ], - "apply_message": "Your skin feels extremely itchy!", + "apply_message": "You feel extremely itchy!", "rating": "bad", + "resist_effects": [ "took_flumed", "took_antihistamine" ], "main_parts_only": true, "max_intensity": 3, "base_mods": { "str_mod": [ -0.34 ], "int_mod": [ -1 ] }, @@ -2795,6 +2796,74 @@ "max_duration": 14515200, "dur_add_perc": 50 }, + { + "//": "For player, indistinguishable from pre_conjunctivitis_bacterial, but separate here to allow for separate resistances from antibiotics.", + "type": "effect_type", + "id": "pre_conjunctivitis_viral", + "show_in_info": false, + "immune_flags": [ "NO_DISEASE", "SEESLEEP" ], + "blood_analysis_description": "Viral Infection", + "max_duration": "71 h" + }, + { + "//": "For player, indistinguishable from pre_conjunctivitis_viral, but separate here to allow for separate resistances from antibiotics.", + "type": "effect_type", + "id": "pre_conjunctivitis_bacterial", + "show_in_info": false, + "immune_flags": [ "NO_DISEASE", "SEESLEEP" ], + "blood_analysis_description": "Bacterial Infection", + "max_duration": "71 h" + }, + { + "//": "For player, indistinguishable from conjunctivitis_bacterial, but separate here to allow for separate resistances from antibiotics.", + "type": "effect_type", + "id": "conjunctivitis_viral", + "name": [ "Conjunctivitis" ], + "desc": [ + "Commonly known as pinkeye, this minor infection can be treated with antihistamines. If it's bacterial, antibiotics may help, but you can't tell without a lab analysis." + ], + "apply_memorial_log": "Got pinkeye.", + "remove_memorial_log": "Got over a pinkeye infection.", + "apply_message": "Your itchy eye leaks a filmy discharge.", + "rating": "bad", + "resist_effects": [ "took_antihistamine", "took_flumed" ], + "resist_traits": [ "INFRESIST", "PER_SLIME_OK" ], + "immune_flags": [ "NO_DISEASE", "SEESLEEP" ], + "int_dur_factor": "50 m", + "base_mods": { "per_mod": [ -2 ], "pain_min": [ 1 ], "pain_chance": [ 400, 1000 ] }, + "limb_score_mods": [ + { "limb_score": "vision", "modifier": 0.8, "resist_modifier": 0.9 }, + { "limb_score": "night_vis", "modifier": 0.8, "resist_modifier": 0.9 } + ], + "miss_messages": [ [ "It feels like there's sand in your eye.", 1 ] ], + "flags": [ "EFFECT_LIMB_SCORE_MOD" ], + "blood_analysis_description": "Viral Infection" + }, + { + "//": "For player, indistinguishable from conjunctivitis_bacterial, but separate here to allow for separate resistances from antibiotics.", + "type": "effect_type", + "id": "conjunctivitis_bacterial", + "name": [ "Conjunctivitis" ], + "desc": [ + "Commonly known as pinkeye, this minor infection can be treated with antihistamines. If it's bacterial, antibiotics may help, but you can't tell without a lab analysis." + ], + "apply_memorial_log": "Got pinkeye.", + "remove_memorial_log": "Got over a pinkeye infection.", + "apply_message": "Your itchy eye leaks a filmy discharge.", + "rating": "bad", + "resist_effects": [ "took_antihistamine", "took_flumed" ], + "resist_traits": [ "INFRESIST", "PER_SLIME_OK" ], + "immune_flags": [ "NO_DISEASE", "SEESLEEP" ], + "int_dur_factor": "50 m", + "base_mods": { "per_mod": [ -2 ], "pain_min": [ 1 ], "pain_chance": [ 400, 1000 ] }, + "miss_messages": [ [ "It feels like there's sand in your eye.", 1 ] ], + "limb_score_mods": [ + { "limb_score": "vision", "modifier": 0.8, "resist_modifier": 0.9 }, + { "limb_score": "night_vis", "modifier": 0.8, "resist_modifier": 0.9 } + ], + "flags": [ "EFFECT_LIMB_SCORE_MOD" ], + "blood_analysis_description": "Bacterial Infection" + }, { "type": "effect_type", "id": "prophylactic_antivenom", @@ -2812,6 +2881,14 @@ "max_duration": 86400, "blood_analysis_description": "Antiasthmatics" }, + { + "type": "effect_type", + "id": "took_antihistamine", + "name": [ "Took Antihistamine Drugs" ], + "desc": [ "You have taken an antihistamine drug recently." ], + "rating": "good", + "blood_analysis_description": "Antihistamines" + }, { "type": "effect_type", "id": "cureall", @@ -2835,7 +2912,9 @@ "infected", "asthma", "common_cold", - "flu" + "flu", + "conjunctivitis_viral", + "conjunctivitis_bacterial" ], "base_mods": { "pkill_min": [ 5 ] } }, @@ -4378,5 +4457,20 @@ ] } ] + }, + { + "id": "slippery_terrain", + "type": "effect_type", + "max_duration": "1 s", + "name": [ "Slick Surface", "Slippery Terrain", "Dangerously Slippery" ], + "desc": [ + "There's a slippery surface here, running may be a bad idea.", + "It's quite slippery, it may not be safe to stand here.", + "This area is extremely slippery and hard to stand up in." + ], + "rating": "bad", + "show_intensity": true, + "resist_traits": [ "GASTROPOD_BALANCE" ], + "show_in_info": true } ] diff --git a/data/json/effects_on_condition/mutation_eocs/mutation_effect_eocs.json b/data/json/effects_on_condition/mutation_eocs/mutation_effect_eocs.json index ab484b2ec2870..0e4fe1246fac8 100644 --- a/data/json/effects_on_condition/mutation_eocs/mutation_effect_eocs.json +++ b/data/json/effects_on_condition/mutation_eocs/mutation_effect_eocs.json @@ -226,8 +226,29 @@ { "type": "effect_on_condition", "id": "EOC_RASHY_SKIN", - "recurrence": [ "2 hour", "24 hours" ], + "recurrence": [ "2 hours", "24 hours" ], "condition": { "and": [ { "u_has_trait": "SKIN_RASHY" }, { "not": { "u_has_effect": "formication" } } ] }, "effect": [ { "u_add_effect": "formication", "duration": "10 minutes", "target_part": "random" } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_PRE_CONJUNCTIVITIS_VIRAL", + "recurrence": [ "24 hours", "72 hours" ], + "condition": { "and": [ { "u_has_effect": "pre_conjunctivitis_viral" }, { "not": { "u_has_effect": "conjunctivitis_bacterial" } }, { "not": { "u_has_effect": "conjunctivitis_viral" } }, { "not": { "u_has_trait": "SEESLEEP" } }, { "not": { "u_has_bionics": "armor_bio_eyes" } } ] }, + "effect": [ { "u_add_effect": "conjunctivitis_viral", "duration": { "math": [ "rand(259200) + 432000" ] }, "target_part": "eyes" }, { "u_lose_effect": "pre_conjunctivitis_bacterial" }, { "u_lose_effect": "pre_conjunctivitis_viral" } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_PRE_CONJUNCTIVITIS_BACTERIAL", + "recurrence": [ "24 hours", "72 hours" ], + "condition": { "and": [ { "u_has_effect": "pre_conjunctivitis_bacterial" }, { "not": { "u_has_effect": "conjunctivitis_bacterial" } }, { "not": { "u_has_effect": "conjunctivitis_viral" } }, { "not": { "u_has_trait": "SEESLEEP" } }, { "not": { "u_has_bionics": "armor_bio_eyes" } } ] }, + "effect": [ { "u_add_effect": "conjunctivitis_bacterial", "duration": { "math": [ "rand(259200) + 432000" ] }, "target_part": "eyes" }, { "u_lose_effect": "pre_conjunctivitis_viral" }, { "u_lose_effect": "pre_conjunctivitis_bacterial" } ] + }, + { + "type": "effect_on_condition", + "id": "EOC_CONJUNCTIVITIS", + "recurrence": [ "10 minutes", "45 minutes" ], + "condition": { "and": [ { "or": [ { "u_has_effect": "conjunctivitis_viral" }, { "u_has_effect": "conjunctivitis_bacterial" } ] }, { "not": { "u_has_effect": "formication" } }, { "not": { "u_has_effect": "took_antihistamine" } }, { "not": { "u_has_effect": "sleep" } } ] }, + "effect": [ { "u_add_effect": "formication", "duration": "5 minutes", "target_part": "head" } ] } ] diff --git a/data/json/field_type.json b/data/json/field_type.json index 203f667578fc2..ecffe1ff7c2fa 100644 --- a/data/json/field_type.json +++ b/data/json/field_type.json @@ -17,12 +17,33 @@ "id": "fd_bile", "type": "field_type", "legacy_enum_id": 2, - "intensity_levels": [ { "name": "bile splatter", "color": "pink" }, { "name": "bile stain" }, { "name": "puddle of bile" } ], + "intensity_levels": [ + { + "name": "bile splatter", + "sym": "}", + "color": "pink", + "effects": [ + { "effect_id": "slippery_terrain", "intensity": 1, "min_duration": "1 second", "immune_in_vehicle": true, "is_environmental": false } + ] + }, + { + "name": "bile stain", + "effects": [ + { "effect_id": "slippery_terrain", "intensity": 2, "min_duration": "1 second", "immune_in_vehicle": true, "is_environmental": false } + ] + }, + { + "name": "puddle of bile", + "effects": [ + { "effect_id": "slippery_terrain", "intensity": 3, "min_duration": "1 second", "immune_in_vehicle": true, "is_environmental": false } + ] + } + ], "description_affix": "covered_in", "underwater_age_speedup": "25 minutes", "decay_amount_factor": 2, "is_splattering": true, - "half_life": "1 days", + "half_life": "30 minutes", "phase": "liquid", "accelerated_decay": true, "display_field": true, @@ -176,15 +197,32 @@ "type": "field_type", "legacy_enum_id": 6, "intensity_levels": [ - { "name": "slime trail", "color": "light_green" }, - { "name": "slime stain" }, - { "name": "puddle of slime", "color": "green" } + { + "name": "slime trail", + "color": "light_green", + "effects": [ + { "effect_id": "slippery_terrain", "intensity": 1, "min_duration": "1 second", "immune_in_vehicle": true, "is_environmental": false } + ] + }, + { + "name": "slime stain", + "effects": [ + { "effect_id": "slippery_terrain", "intensity": 2, "min_duration": "1 second", "immune_in_vehicle": true, "is_environmental": false } + ] + }, + { + "name": "puddle of slime", + "color": "green", + "effects": [ + { "effect_id": "slippery_terrain", "intensity": 3, "min_duration": "1 second", "immune_in_vehicle": true, "is_environmental": false } + ] + } ], "description_affix": "covered_in", "decay_amount_factor": 2, "apply_slime_factor": 10, "is_splattering": true, - "half_life": "1 days", + "half_life": "25 minutes", "phase": "liquid", "accelerated_decay": true, "display_field": true, diff --git a/data/json/flags.json b/data/json/flags.json index 500272d96b14c..a2676840cc14e 100644 --- a/data/json/flags.json +++ b/data/json/flags.json @@ -2347,5 +2347,10 @@ "id": "ROOTS3", "type": "json_flag", "info": "The character has extensive roots, which helps with the TREE_COMMUNION mutation." + }, + { + "id": "NON_SLIP", + "type": "json_flag", + "info": "The character can't slip on slippery surfaces." } ] diff --git a/data/json/itemgroups/Drugs_Tobacco_Alcohol/drugs.json b/data/json/itemgroups/Drugs_Tobacco_Alcohol/drugs.json index c8cdd576793bf..a517770443d78 100644 --- a/data/json/itemgroups/Drugs_Tobacco_Alcohol/drugs.json +++ b/data/json/itemgroups/Drugs_Tobacco_Alcohol/drugs.json @@ -227,6 +227,7 @@ { "prob": 25, "group": "caffeine_bottle_plastic_pill_supplement_1_10" }, { "prob": 15, "group": "pills_sleep_bottle_plastic_pill_prescription_1_10" }, { "prob": 10, "group": "melatonin_tablet_bottle_plastic_pill_supplement_1_30" }, + { "prob": 15, "group": "antihistamine_bottle_plastic_pill_supplement_1_30" }, { "prob": 5, "group": "iodine_bottle_plastic_pill_supplement_1_10" }, { "prob": 5, "group": "prussian_blue_bottle_plastic_pill_supplement_1_10" }, { "item": "dayquil", "prob": 70, "charges": [ 1, 5 ] }, @@ -585,6 +586,13 @@ "container-item": "bottle_plastic_pill_prescription", "entries": [ { "item": "melatonin_tablet", "container-item": "null", "count": 30 } ] }, + { + "type": "item_group", + "id": "antihistamine_bottle_full", + "subtype": "collection", + "container-item": "bottle_plastic_pill_prescription", + "entries": [ { "item": "antihistamine", "container-item": "null", "count": 30 } ] + }, { "type": "item_group", "id": "protein_bottle_full", diff --git a/data/json/itemgroups/collections_domestic.json b/data/json/itemgroups/collections_domestic.json index 03512ba0a76fc..3ab6eb2d85961 100644 --- a/data/json/itemgroups/collections_domestic.json +++ b/data/json/itemgroups/collections_domestic.json @@ -277,6 +277,7 @@ [ "holy_symbol", 5 ], [ "pills_sleep", 5 ], { "prob": 3, "group": "melatonin_tablet_bottle_plastic_pill_supplement_1_30" }, + { "prob": 5, "group": "antihistamine_bottle_plastic_pill_supplement_1_30" }, { "item": "nyquil", "prob": 5, "charges": [ 1, 5 ] }, { "group": "mansion_guns", "prob": 3 }, { "group": "harddrugs", "prob": 1 }, @@ -1491,6 +1492,13 @@ "container-item": "bottle_plastic_pill_supplement", "entries": [ { "item": "melatonin_tablet", "container-item": "null", "count": [ 1, 30 ] } ] }, + { + "type": "item_group", + "id": "antihistamine_bottle_plastic_pill_supplement_1_30", + "subtype": "collection", + "container-item": "bottle_plastic_pill_supplement", + "entries": [ { "item": "antihistamine", "container-item": "null", "count": [ 1, 30 ] } ] + }, { "type": "item_group", "id": "coke_bag_zipper_1_8", diff --git a/data/json/itemgroups/stashes.json b/data/json/itemgroups/stashes.json index 0e45867144918..9da35aef422ca 100644 --- a/data/json/itemgroups/stashes.json +++ b/data/json/itemgroups/stashes.json @@ -56,6 +56,7 @@ "id": "stash_drugs", "items": [ { "prob": 15, "group": "pills_sleep_bottle_plastic_pill_prescription_1_10" }, + { "prob": 10, "group": "antihistamine_bottle_plastic_pill_supplement_1_30" }, { "prob": 5, "group": "melatonin_tablet_bottle_plastic_pill_supplement_1_30" }, { "prob": 4, "group": "oxycodone_bottle_plastic_pill_prescription_1_10" }, { "item": "morphine", "prob": 4, "count": [ 1, 4 ] }, diff --git a/data/json/items/armor/eyewear.json b/data/json/items/armor/eyewear.json index e5415dffcbbe3..0f193126ed84d 100644 --- a/data/json/items/armor/eyewear.json +++ b/data/json/items/armor/eyewear.json @@ -94,7 +94,7 @@ "material_thickness": 3, "environmental_protection": 4, "flags": [ "WATER_FRIENDLY", "SUN_GLASSES", "SKINTIGHT" ], - "armor": [ { "encumbrance": 5, "coverage": 100, "covers": [ "eyes" ], "rigid_layer_only": true } ] + "armor": [ { "encumbrance": 5, "coverage": 95, "covers": [ "eyes" ], "rigid_layer_only": true } ] }, { "id": "glasses_bifocal", diff --git a/data/json/items/comestibles/med.json b/data/json/items/comestibles/med.json index 46787122f2bae..aa24f531d631b 100644 --- a/data/json/items/comestibles/med.json +++ b/data/json/items/comestibles/med.json @@ -913,6 +913,30 @@ "addiction_type": "sleeping pill", "use_action": [ "FLUSLEEP" ] }, + { + "id": "antihistamine", + "type": "COMESTIBLE", + "comestible_type": "MED", + "name": { "str_sp": "antihistamine pill" }, + "description": "Over-the-counter allergy medication. The label advises taking one a day and warns that they can cause drowsiness.", + "//": "Flu meds contain antihistamines among other things, so it's intended that there's some overlap between this and cough syrup.", + "weight": "1 g", + "volume": "1 ml", + "price": "25 cent", + "price_postapoc": "25 cent", + "symbol": "!", + "color": "light_red", + "container": "bottle_plastic_pill_supplement", + "stim": -6, + "flags": [ "IRREPLACEABLE_CONSUMABLE" ], + "addiction_potential": 4, + "addiction_type": "sleeping pill", + "use_action": { + "type": "consume_drug", + "activation_message": "You take an antihistamine pill.", + "effects": [ { "id": "took_antihistamine", "duration": "10 h" } ] + } + }, { "id": "oxycodone", "type": "COMESTIBLE", diff --git a/src/character.cpp b/src/character.cpp index 5821c067d71f1..b20371a0d8172 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -209,6 +209,7 @@ static const efftype_id effect_alarm_clock( "alarm_clock" ); static const efftype_id effect_bandaged( "bandaged" ); static const efftype_id effect_beartrap( "beartrap" ); static const efftype_id effect_bite( "bite" ); +static const efftype_id effect_slippery_terrain( "slippery_terrain" ); static const efftype_id effect_bleed( "bleed" ); static const efftype_id effect_blind( "blind" ); static const efftype_id effect_blood_spiders( "blood_spiders" ); @@ -256,6 +257,10 @@ static const efftype_id effect_paincysts( "paincysts" ); static const efftype_id effect_pkill1( "pkill1" ); static const efftype_id effect_pkill2( "pkill2" ); static const efftype_id effect_pkill3( "pkill3" ); +static const efftype_id effect_pre_conjunctivitis_viral( "pre_conjunctivitis_viral" ); +static const efftype_id effect_pre_conjunctivitis_bacterial( "pre_conjunctivitis_bacterial" ); +static const efftype_id effect_conjunctivitis_viral( "conjunctivitis_viral" ); +static const efftype_id effect_conjunctivitis_bacterial( "conjunctivitis_bacterial" ); static const efftype_id effect_recently_coughed( "recently_coughed" ); static const efftype_id effect_recover( "recover" ); static const efftype_id effect_ridden( "ridden" ); @@ -309,7 +314,7 @@ static const json_character_flag json_flag_IMMUNE_HEARING_DAMAGE( "IMMUNE_HEARIN static const json_character_flag json_flag_INFECTION_IMMUNE( "INFECTION_IMMUNE" ); static const json_character_flag json_flag_INFRARED( "INFRARED" ); static const json_character_flag json_flag_INSECTBLOOD( "INSECTBLOOD" ); -static const json_character_flag json_flag_INVERTERBRATEBLOOD( "INVERTERBRATEBLOOD" ); +static const json_character_flag json_flag_INVERTEBRATEBLOOD( "INVERTEBRATEBLOOD" ); static const json_character_flag json_flag_INVISIBLE( "INVISIBLE" ); static const json_character_flag json_flag_MYOPIC( "MYOPIC" ); static const json_character_flag json_flag_MYOPIC_IN_LIGHT( "MYOPIC_IN_LIGHT" ); @@ -398,6 +403,7 @@ static const start_location_id start_location_sloc_shelter( "sloc_shelter" ); static const trait_id trait_ADRENALINE( "ADRENALINE" ); static const trait_id trait_ANTENNAE( "ANTENNAE" ); +static const trait_id trait_AQUEOUS( "AQUEOUS" ); static const trait_id trait_BADBACK( "BADBACK" ); static const trait_id trait_BIRD_EYE( "BIRD_EYE" ); static const trait_id trait_BOOMING_VOICE( "BOOMING_VOICE" ); @@ -408,6 +414,7 @@ static const trait_id trait_CF_HAIR( "CF_HAIR" ); static const trait_id trait_CHEMIMBALANCE( "CHEMIMBALANCE" ); static const trait_id trait_CHLOROMORPH( "CHLOROMORPH" ); static const trait_id trait_CLUMSY( "CLUMSY" ); +static const trait_id trait_COMPOUND_EYES( "COMPOUND_EYES" ); static const trait_id trait_DEBUG_CLOAK( "DEBUG_CLOAK" ); static const trait_id trait_DEBUG_HS( "DEBUG_HS" ); static const trait_id trait_DEBUG_LS( "DEBUG_LS" ); @@ -431,12 +438,14 @@ static const trait_id trait_HEAVYSLEEPER( "HEAVYSLEEPER" ); static const trait_id trait_HEAVYSLEEPER2( "HEAVYSLEEPER2" ); static const trait_id trait_HIBERNATE( "HIBERNATE" ); static const trait_id trait_ILLITERATE( "ILLITERATE" ); +static const trait_id trait_INFRESIST( "INFRESIST" ); static const trait_id trait_INSOMNIA( "INSOMNIA" ); static const trait_id trait_INT_SLIME( "INT_SLIME" ); static const trait_id trait_LEG_TENT_BRACE( "LEG_TENT_BRACE" ); static const trait_id trait_LIGHTSTEP( "LIGHTSTEP" ); static const trait_id trait_LOVES_BOOKS( "LOVES_BOOKS" ); static const trait_id trait_MASOCHIST( "MASOCHIST" ); +static const trait_id trait_MUCUS_SECRETION( "MUCUS_SECRETION" ); static const trait_id trait_MUTE( "MUTE" ); static const trait_id trait_M_IMMUNE( "M_IMMUNE" ); static const trait_id trait_M_SKIN3( "M_SKIN3" ); @@ -747,7 +756,7 @@ field_type_id Character::bloodType() const if( has_flag( json_flag_INSECTBLOOD ) ) { return fd_blood_insect; } - if( has_flag( json_flag_INVERTERBRATEBLOOD ) ) { + if( has_flag( json_flag_INVERTEBRATEBLOOD ) ) { return fd_blood_invertebrate; } return fd_blood; @@ -1845,12 +1854,19 @@ void Character::dismount() } } +float Character::balance_roll() const +{ + /** @EFFECT_DEX improves player balance roll */ + /** Balance and reaction scores influence stability rolls */ + /** @EFFECT_SWIMMING improves player stability roll */ + return ( get_dex() + get_skill_level( skill_swimming ) ) * ( ( get_limb_score( limb_score_balance ) * 3 + get_limb_score( + limb_score_reaction ) ) / 4.0f ); +} + float Character::stability_roll() const { /** @EFFECT_STR improves player stability roll */ - /** Balance and reaction scores influence stability rolls */ - /** @EFFECT_MELEE improves player stability roll */ return ( get_melee() + get_str() ) * ( ( get_limb_score( limb_score_balance ) * 3 + get_limb_score( limb_score_reaction ) ) / 4.0f ); @@ -7980,7 +7996,7 @@ void Character::on_hit( Creature *source, bodypart_id bp_hit, } } - map &here = get_map(); +map &here = get_map(); const optional_vpart_position veh_part = here.veh_at( pos() ); bool in_skater_vehicle = in_vehicle && veh_part.part_with_feature( "SEAT_REQUIRES_BALANCE", false ); @@ -8018,6 +8034,7 @@ void Character::on_hit( Creature *source, bodypart_id bp_hit, enchantment_cache->cast_hit_me( *this, source ); } + /* Where damage to character is actually applied to hit body parts Might be where to put bleed stuff rather than in player::deal_damage() @@ -10706,6 +10723,62 @@ void Character::process_effects() terminating_effects.pop(); } + if ( has_effect( effect_boomered ) && ( is_avatar() || is_npc() ) && one_in( 10 ) && !has_trait ( trait_COMPOUND_EYES ) && !has_effect( effect_pre_conjunctivitis_bacterial ) && !has_effect( effect_pre_conjunctivitis_viral ) && !has_effect( effect_conjunctivitis_bacterial ) && !has_effect( effect_conjunctivitis_viral ) ) { + //Washing your eyes out in time may save you from getting pinkeye. + float checked_health = get_lifestyle() + 200.0; + //Some animal eyes are more vulnerable to infection. + if ( has_trait_flag( json_flag_EYE_MEMBRANE ) ) { + checked_health -= 50; + } + //Ditto for contact lenses. + if ( has_effect( effect_contacts ) ) { + checked_health -= 50; + } + if( has_trait( trait_INFRESIST ) ) { + checked_health += 50; + } + int pinkeye_chance = round( 4 + 6 / 25 * checked_health ); + if( one_in( ( pinkeye_chance ) ) ) { + if( one_in( 2 ) ) { + add_effect( effect_pre_conjunctivitis_bacterial, 70_hours ); + } else { + add_effect( effect_pre_conjunctivitis_viral, 70_hours ); + } + } + } + + map &here = get_map(); + if( has_effect( effect_slippery_terrain ) && !is_on_ground() && !is_crouching() && here.has_flag( ter_furn_flag::TFLAG_FLAT, pos() ) ) { + int rolls = 1; + bool u_see = get_player_view().sees( *this ); + if( has_trait( trait_DEFT ) ) { + rolls--; + } + if( is_running() || ( ( worn_with_flag( flag_ROLLER_ONE ) || worn_with_flag( flag_ROLLER_INLINE ) || worn_with_flag( flag_ROLLER_QUAD ) ) && !has_trait( trait_PROF_SKATER ) ) ) { + rolls++; + } + //Slimy people are used to everything being slippery. + if( has_trait( trait_SLIMY ) || has_trait( trait_AQUEOUS ) || has_trait( trait_MUCUS_SECRETION ) ) { + rolls--; + } + if( has_trait( trait_CLUMSY ) ) { + rolls++; + } + int intensity = get_effect_int( effect_slippery_terrain ); + rolls += intensity; + //A healthy unencumbered person with 18 dex can usually walk across a moderately slippery surface without issue. + //Survivors rarely meet those qualifications in practice. + if( balance_roll() < dice( rolls, 6 ) ) { + if( !is_avatar() ) { + if( u_see ) { + add_msg( _( "%1$s slips and falls!" ), get_name() ); + } + } else { + add_msg( m_bad, _( "You lose your balance and fall on the slippery ground!" ) ); + } + add_effect( effect_downed, rng( 1_turns, 2_turns ) ); + } + } Creature::process_effects(); } diff --git a/src/character.h b/src/character.h index 3545f69d3e64e..d0ef7d42093d9 100644 --- a/src/character.h +++ b/src/character.h @@ -1177,7 +1177,9 @@ class Character : public Creature, public visitable bool is_stealthy() const; /** Returns true if the current martial art works with the player's current weapon */ bool can_melee() const; - /** Returns value of player's stable footing */ + /** Returns value of player's footing on narrow or slippery terrain */ + float balance_roll() const; + /** Returns value of player's footing on skates or similar */ float stability_roll() const override; /** Returns true if the player can learn the entered martial art */ bool can_autolearn( const matype_id &ma_id ) const; diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 42ac0c411fd88..d0384df354cce 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -2608,10 +2608,6 @@ float outfit::clothing_wetness_mult( const bodypart_id &bp ) const clothing_mult = std::min( clothing_mult, breathability ); } } - - // always some evaporation even if completely covered - // doesn't handle things that would be "air tight" - clothing_mult = std::max( clothing_mult, .1f ); return clothing_mult; } diff --git a/src/character_body.cpp b/src/character_body.cpp index 4557e49478d4d..d610585b04c24 100644 --- a/src/character_body.cpp +++ b/src/character_body.cpp @@ -132,7 +132,11 @@ void Character::update_body_wetness( const w_point &weather ) } // Make clothing slow down drying - const float clothing_mult = worn.clothing_wetness_mult( bp ); + + const float base_clothing_mult = worn.clothing_wetness_mult( bp ); + // always some evaporation even if completely covered + // doesn't handle things that would be "air tight" + const float clothing_mult = std::max( base_clothing_mult, .1f ); const time_duration drying = bp->drying_increment * average_drying * trait_mult * weather_mult * temp_mult / clothing_mult; diff --git a/src/creature.cpp b/src/creature.cpp index 11b257baa79e1..e83a35c0aff70 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -1680,6 +1680,40 @@ bool Creature::add_env_effect( const efftype_id &eff_id, const bodypart_id &vect return add_env_effect( eff_id, vector, strength, dur, bodypart_str_id::NULL_ID(), permanent, intensity, force ); } + +bool Creature::add_liquid_effect( const efftype_id &eff_id, const bodypart_id &vector, int strength, + const time_duration &dur, const bodypart_id &bp, bool permanent, int intensity, bool force ) +{ + if( !force && is_immune_effect( eff_id ) ) { + return false; + } + if( is_monster() ) { + if( dice( strength, 3 ) > dice( get_env_resist( vector ), 3 ) ) { + //Monsters don't have clothing wetness multipliers, so we still use enviro for them. + add_effect( effect_source::empty(), eff_id, dur, bodypart_str_id::NULL_ID(), permanent, intensity, true ); + return true; + } else { + return false; + } + } + const Character *c = as_character(); + //d100 minus strength should never be less than 1 so we don't have liquids phasing through sealed power armor. + if( ( std::max( dice( 1, 100 ) - strength, 1 ) ) < ( c->worn.clothing_wetness_mult( vector ) * 100 ) ) { + // Don't check immunity (force == true), because we did check above + add_effect( effect_source::empty(), eff_id, dur, bp, permanent, intensity, true ); + return true; + } else { + //To do: make absorbent armor filthy, damage it with acid, etc + return false; + } +} +bool Creature::add_liquid_effect( const efftype_id &eff_id, const bodypart_id &vector, int strength, + const time_duration &dur, bool permanent, int intensity, bool force ) +{ + return add_liquid_effect( eff_id, vector, strength, dur, bodypart_str_id::NULL_ID(), permanent, + intensity, force ); +} + void Creature::clear_effects() { for( auto &elem : *effects ) { diff --git a/src/creature.h b/src/creature.h index 762f9ee80203e..143ad6216c3e2 100644 --- a/src/creature.h +++ b/src/creature.h @@ -628,6 +628,13 @@ class Creature : public viewer bool force = false ); bool add_env_effect( const efftype_id &eff_id, const bodypart_id &vector, int strength, const time_duration &dur, bool permanent = false, int intensity = 1, bool force = false ); + /** Applies effects by spraying liquid on the creature. Returns false if the liquid was blocked + * by waterproof gear. */ + bool add_liquid_effect( const efftype_id &eff_id, const bodypart_id &vector, int strength, + const time_duration &dur, const bodypart_id &bp, bool permanent = false, int intensity = 1, + bool force = false ); + bool add_liquid_effect( const efftype_id &eff_id, const bodypart_id &vector, int strength, + const time_duration &dur, bool permanent = false, int intensity = 1, bool force = false ); /** Removes a listed effect. If the bodypart is not specified remove all effects of * a given type, targeted or untargeted. Returns true if anything was * removed. */ diff --git a/src/iuse.cpp b/src/iuse.cpp index 553152b938a3a..7f7fe63ca1e6c 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -167,6 +167,8 @@ static const efftype_id effect_brainworms( "brainworms" ); static const efftype_id effect_cig( "cig" ); static const efftype_id effect_contacts( "contacts" ); static const efftype_id effect_corroding( "corroding" ); +static const efftype_id effect_conjunctivitis_bacterial( "conjunctivitis_bacterial" ); +static const efftype_id effect_conjunctivitis_viral( "conjunctivitis_viral" ); static const efftype_id effect_crushed( "crushed" ); static const efftype_id effect_datura( "datura" ); static const efftype_id effect_dazed( "dazed" ); @@ -203,6 +205,7 @@ static const efftype_id effect_onfire( "onfire" ); static const efftype_id effect_paincysts( "paincysts" ); static const efftype_id effect_pet( "pet" ); static const efftype_id effect_poison( "poison" ); +static const efftype_id effect_pre_conjunctivitis_bacterial( "pre_conjunctivitis_bacterial" ); static const efftype_id effect_ridden( "ridden" ); static const efftype_id effect_riding( "riding" ); static const efftype_id effect_run( "run" ); @@ -644,6 +647,24 @@ std::optional iuse::antibiotic( Character *p, item *, const tripoint & ) p->add_msg_if_player( m_warning, _( "The medication does nothing to help the spasms." ) ); } } + if( p->has_effect( effect_conjunctivitis_bacterial ) ) { + if( one_in( 2 ) ) { + p->remove_effect( effect_conjunctivitis_bacterial ); + p->add_msg_if_player( m_good, _( "Your pinkeye seems to be clearing up." ) ); + } else { + p->add_msg_if_player( m_warning, _( "Your pinkeye doesn't feel any better." ) ); + } + } + if( p->has_effect( effect_pre_conjunctivitis_bacterial ) ) { + if( one_in( 2 ) ) { + //There were no symptoms yet, so we skip telling the player they feel better. + p->remove_effect( effect_pre_conjunctivitis_bacterial ); + } + } + if( p->has_effect( effect_conjunctivitis_viral ) ) { + //Antibiotics don't kill viruses. + p->add_msg_if_player( m_warning, _( "Your pinkeye doesn't feel any better." ) ); + } if( p->has_effect( effect_infected ) && !p->has_effect( effect_antibiotic ) ) { p->add_msg_if_player( m_good, _( "Maybe this is just the placebo effect, but you feel a little better as the dose settles in." ) ); diff --git a/src/monattack.cpp b/src/monattack.cpp index 443c1854d94f4..db1b10dd69a94 100644 --- a/src/monattack.cpp +++ b/src/monattack.cpp @@ -134,6 +134,8 @@ static const efftype_id effect_operating( "operating" ); static const efftype_id effect_paid( "paid" ); static const efftype_id effect_paralyzepoison( "paralyzepoison" ); static const efftype_id effect_pet( "pet" ); +static const efftype_id effect_pre_conjunctivitis_bacterial( "pre_conjunctivitis_bacterial" ); +static const efftype_id effect_pre_conjunctivitis_viral( "pre_conjunctivitis_viral" ); static const efftype_id effect_raising( "raising" ); static const efftype_id effect_rat( "rat" ); static const efftype_id effect_shrieking( "shrieking" ); @@ -734,7 +736,7 @@ bool mattack::acid_barf( monster *z ) int dam = target->deal_damage( z, hit, dam_inst ).total_damage(); - target->add_env_effect( effect_corroding, hit, 5, time_duration::from_turns( dam / 2 + 5 ), hit ); + target->add_liquid_effect( effect_corroding, hit, 5, time_duration::from_turns( dam / 2 + 5 ), hit ); if( dam > 0 ) { game_message_type msg_type = target->is_avatar() ? m_bad : m_info; @@ -748,7 +750,7 @@ bool mattack::acid_barf( monster *z ) dam ); if( hit == bodypart_id( "eyes" ) ) { - target->add_env_effect( effect_blind, bodypart_id( "eyes" ), 3, 1_minutes ); + target->add_liquid_effect( effect_blind, bodypart_id( "eyes" ), 3, 1_minutes ); } } else { target->add_msg_player_or_npc( @@ -980,7 +982,7 @@ bool mattack::boomer( monster *z ) } if( !target->dodge_check( z ) ) { - target->add_env_effect( effect_boomered, bodypart_id( "eyes" ), 3, 12_turns ); + target->add_liquid_effect( effect_boomered, bodypart_id( "eyes" ), 3, 12_turns ); } else if( u_see ) { target->add_msg_player_or_npc( _( "You dodge it!" ), _( " dodges it!" ) ); @@ -1020,11 +1022,11 @@ bool mattack::boomer_glow( monster *z ) } if( !target->dodge_check( z ) ) { - target->add_env_effect( effect_boomered, bodypart_id( "eyes" ), 5, 25_turns ); + target->add_liquid_effect( effect_boomered, bodypart_id( "eyes" ), 5, 25_turns ); target->on_dodge( z, 5 ); for( int i = 0; i < rng( 2, 4 ); i++ ) { const bodypart_id &bp = target->random_body_part(); - target->add_env_effect( effect_glowing, bp, 4, 4_minutes ); + target->add_liquid_effect( effect_glowing, bp, 4, 4_minutes ); if( target->has_effect( effect_glowing ) ) { break; } diff --git a/src/monster.cpp b/src/monster.cpp index 34c5c0ed34fc3..8dcc546c36224 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -111,6 +111,7 @@ static const efftype_id effect_photophobia( "photophobia" ); static const efftype_id effect_poison( "poison" ); static const efftype_id effect_ridden( "ridden" ); static const efftype_id effect_run( "run" ); +static const efftype_id effect_slippery_terrain( "slippery_terrain" ); static const efftype_id effect_spooked( "spooked" ); static const efftype_id effect_spooked_recent( "spooked_recent" ); static const efftype_id effect_stunned( "stunned" ); @@ -3256,6 +3257,20 @@ void monster::process_effects() } } + // Check to see if critter slips on bile or whatever. + if( has_effect( effect_slippery_terrain ) && !is_immune_effect( effect_downed ) && !flies() && !digging() && !has_effect( effect_downed ) ) { + map &here = get_map(); + if( here.has_flag( ter_furn_flag::TFLAG_FLAT, pos() ) ) { + int intensity = get_effect_int( effect_slippery_terrain ); + int slipchance = ( round( get_speed() / 50 ) - round( get_dodge() / 3 ) ); + if ( intensity + slipchance > ( dice( 1, 12 ) ) ) { + add_effect( effect_downed, rng( 1_turns, 2_turns ) ); + add_msg_if_player_sees( pos(), m_info, _( "The %1s slips and falls!" ), + name() ); + } + } + } + Creature::process_effects(); }