From 13f8d81b4830226ad24345d0dcf1b00fc3fd5dad Mon Sep 17 00:00:00 2001 From: Dan1ss1mo <112878543+Dan1ss1mo@users.noreply.github.com> Date: Sat, 15 Apr 2023 07:44:59 +0300 Subject: [PATCH] Pain immunity flag + flat pain modifier (#63636) * jsonized suffering * linting * more linting * Update character.cpp * linting linting * Update character.cpp * Update character.cpp * some fixes * more fixes * Update src/character.cpp Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update character.cpp * Update character.cpp * Squashed commit of the following: commit c6d7d314b5900cdaeb2723ead8e5f8200f9911bf Author: Dan1ss1mo <112878543+Dan1ss1mo@users.noreply.github.com> Date: Wed Mar 8 19:34:50 2023 +0300 Update torso_armor.json commit 6d44c3a4a9334f256a85736fe83198374772c26b Author: Dan1ss1mo <112878543+Dan1ss1mo@users.noreply.github.com> Date: Wed Mar 8 19:34:02 2023 +0300 Update torso_armor.json commit f1531053d5ec576b22d4bdca4a1e5ecb86c5b1ef Author: Dan1ss1mo <112878543+Dan1ss1mo@users.noreply.github.com> Date: Wed Mar 8 19:29:10 2023 +0300 Update suits_protection.json commit 2f71c08df21be86657a19fe7fc2616f74bde1332 Author: KHeket <102726167+KHeket@users.noreply.github.com> Date: Wed Mar 8 18:12:52 2023 +0300 Freezer recipe and disassemble (#63895) Recipe for freezer and disassemble functionality for it * Update src/activity_handlers.cpp Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * docs * Update MUTATIONS.md * Update mutation.h * fix constant ordering * ordering * Update iuse.cpp --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Kevin Granade --- data/json/flags.json | 4 ++++ data/json/mutations/mutations.json | 3 ++- doc/MUTATIONS.md | 1 + src/activity_handlers.cpp | 5 +++-- src/avatar.cpp | 4 ++-- src/bionics.cpp | 12 ++++++------ src/character.cpp | 15 +++++++++++---- src/character_body.cpp | 4 ++-- src/flag.cpp | 1 + src/flag.h | 1 + src/game_inventory.cpp | 5 +++-- src/iexamine.cpp | 4 ++-- src/iuse.cpp | 8 ++++---- src/medical_ui.cpp | 4 ++-- src/mutation.h | 1 + src/mutation_data.cpp | 1 + src/player_hardcoded_effects.cpp | 4 ++-- src/sounds.cpp | 5 +++-- src/suffer.cpp | 10 +++++----- 19 files changed, 56 insertions(+), 36 deletions(-) diff --git a/data/json/flags.json b/data/json/flags.json index 57dce0fbfc388..e854f3162afe8 100644 --- a/data/json/flags.json +++ b/data/json/flags.json @@ -1725,6 +1725,10 @@ "id": "TOUGH_FEET", "type": "json_flag" }, + { + "id": "PAIN_IMMUNE", + "type": "json_flag" + }, { "id": "TOURNIQUET", "type": "json_flag" diff --git a/data/json/mutations/mutations.json b/data/json/mutations/mutations.json index 172c649d8dc7f..6e5f59180339f 100644 --- a/data/json/mutations/mutations.json +++ b/data/json/mutations/mutations.json @@ -4464,7 +4464,8 @@ "prereqs2": [ "PAINREC3" ], "threshreq": [ "THRESH_MEDICAL" ], "//": "MASOCHIST_MED, CENOBITE, and NOPAIN don't cancel each other. By design. Poor painless people...", - "category": [ "MEDICAL" ] + "category": [ "MEDICAL" ], + "flags": [ "PAIN_IMMUNE" ] }, { "type": "mutation", diff --git a/doc/MUTATIONS.md b/doc/MUTATIONS.md index bd597bc6def5f..b8c1659960057 100644 --- a/doc/MUTATIONS.md +++ b/doc/MUTATIONS.md @@ -239,6 +239,7 @@ Note that **all new traits that can be obtained through mutation must be purifia "deactivated_eocs": [ "eoc_id_1" ], // List of effect_on_conditions that attempt to activate when this mutation is successfully deactivated. "enchantments": [ "ench_id_1" ], // List of enchantments granted by this mutation. Can be either IDs or an inline definition of the enchantment (see MAGIC.md) "temperature_speed_modifier": 0.5, // If nonzero, become slower when cold, and faster when hot (1.0 gives +/-1% speed for each degree above or below 65 F). + "pain_modifier": 5, // Flat increase (for positive numbers)\ reduction (for negative) to the amount of pain recived. Reduction can go all the way to 0. Applies after pain enchantment. (so if you have Pain Resistant trait along with 5 flat pain reduction and recive 20 pain, you would gain 20*(1-0.25)-5=10 pain) "mana_modifier": 100, // Positive or negative change to total mana pool. "flags": [ "UNARMED_BONUS" ], // List of flag_IDs and json_flag_IDs granted by the mutation. Note: trait_IDs can be set and generate no errors, but they're not actually "active". "moncams": [ [ "mon_player_blob", 16 ] ] // Monster cameras, ability to use friendly monster's from the list as additional source of vision. Max view distance is equal to monster's daytime vision. The number specifies the range at which it can "transmit" vision to the avatar. diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index 06498e0540a05..30514974ac4ef 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -191,6 +191,7 @@ static const itype_id itype_burnt_out_bionic( "burnt_out_bionic" ); static const itype_id itype_muscle( "muscle" ); static const json_character_flag json_flag_CANNIBAL( "CANNIBAL" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); static const json_character_flag json_flag_PSYCHOPATH( "PSYCHOPATH" ); static const json_character_flag json_flag_SAPIOVORE( "SAPIOVORE" ); @@ -208,7 +209,6 @@ static const species_id species_HUMAN( "HUMAN" ); static const species_id species_ZOMBIE( "ZOMBIE" ); static const trait_id trait_DEBUG_HS( "DEBUG_HS" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_SPIRITUAL( "SPIRITUAL" ); static const trait_id trait_STOCKY_TROGLO( "STOCKY_TROGLO" ); @@ -2857,7 +2857,8 @@ void activity_handlers::operation_do_turn( player_activity *act, Character *you Character &player_character = get_player_character(); const bool u_see = player_character.sees( you->pos() ) && ( !player_character.has_effect( effect_narcosis ) || - player_character.has_bionic( bio_painkiller ) || player_character.has_trait( trait_NOPAIN ) ); + player_character.has_bionic( bio_painkiller ) || + player_character.has_flag( json_flag_PAIN_IMMUNE ) ); const int difficulty = act->values.front(); diff --git a/src/avatar.cpp b/src/avatar.cpp index 3b8d3ff79a755..ac7ee4f17cae8 100644 --- a/src/avatar.cpp +++ b/src/avatar.cpp @@ -108,6 +108,7 @@ static const itype_id itype_guidebook( "guidebook" ); static const itype_id itype_mut_longpull( "mut_longpull" ); static const json_character_flag json_flag_ALARMCLOCK( "ALARMCLOCK" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); static const json_character_flag json_flag_WEBBED_HANDS( "WEBBED_HANDS" ); static const move_mode_id move_mode_crouch( "crouch" ); @@ -129,7 +130,6 @@ static const trait_id trait_DEBUG_CLOAK( "DEBUG_CLOAK" ); static const trait_id trait_INSECT_ARMS( "INSECT_ARMS" ); static const trait_id trait_INSECT_ARMS_OK( "INSECT_ARMS_OK" ); static const trait_id trait_M_SKIN3( "M_SKIN3" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_PROF_DICEMASTER( "PROF_DICEMASTER" ); static const trait_id trait_SHELL2( "SHELL2" ); static const trait_id trait_SHELL3( "SHELL3" ); @@ -1793,7 +1793,7 @@ void avatar::reassign_item( item &it, int invlet ) void avatar::add_pain_msg( int val, const bodypart_id &bp ) const { - if( has_trait( trait_NOPAIN ) ) { + if( has_flag( json_flag_PAIN_IMMUNE ) ) { return; } if( bp == bodypart_id( "bp_null" ) ) { diff --git a/src/bionics.cpp b/src/bionics.cpp index 295ce94a867d2..84e818a67acdc 100644 --- a/src/bionics.cpp +++ b/src/bionics.cpp @@ -162,6 +162,7 @@ static const json_character_flag json_flag_BIONIC_POWER_SOURCE( "BIONIC_POWER_SO static const json_character_flag json_flag_BIONIC_TOGGLED( "BIONIC_TOGGLED" ); static const json_character_flag json_flag_BIONIC_WEAPON( "BIONIC_WEAPON" ); static const json_character_flag json_flag_ENHANCED_VISION( "ENHANCED_VISION" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); static const material_id fuel_type_metabolism( "metabolism" ); static const material_id fuel_type_sun_light( "sunlight" ); @@ -189,7 +190,6 @@ static const trait_id trait_DEBUG_BIONICS( "DEBUG_BIONICS" ); static const trait_id trait_MASOCHIST( "MASOCHIST" ); static const trait_id trait_MASOCHIST_MED( "MASOCHIST_MED" ); static const trait_id trait_NONE( "NONE" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_PROF_AUTODOC( "PROF_AUTODOC" ); static const trait_id trait_PROF_MED( "PROF_MED" ); static const trait_id trait_PYROMANIA( "PYROMANIA" ); @@ -1807,7 +1807,7 @@ void Character::bionics_uninstall_failure( int difficulty, int success, float ad std::set bp_hurt; switch( fail_type ) { case 1: - if( !has_trait( trait_NOPAIN ) ) { + if( !has_flag( json_flag_PAIN_IMMUNE ) ) { add_msg_if_player( m_bad, _( "It really hurts!" ) ); mod_pain( rng( 10, 30 ) ); } @@ -1894,7 +1894,7 @@ void Character::bionics_uninstall_failure( monster &installer, Character &patien std::set bp_hurt; switch( fail_type ) { case 1: - if( !has_trait( trait_NOPAIN ) ) { + if( !has_flag( json_flag_PAIN_IMMUNE ) ) { patient.add_msg_if_player( m_bad, _( "It really hurts!" ) ); patient.mod_pain( rng( 10, 30 ) ); } @@ -1947,7 +1947,7 @@ bool Character::has_enough_anesth( const itype &cbm, Character &patient ) const return false; } - if( patient.has_bionic( bio_painkiller ) || patient.has_trait( trait_NOPAIN ) || + if( patient.has_bionic( bio_painkiller ) || patient.has_flag( json_flag_PAIN_IMMUNE ) || has_trait( trait_DEBUG_BIONICS ) ) { return true; } @@ -1961,7 +1961,7 @@ bool Character::has_enough_anesth( const itype &cbm, Character &patient ) const bool Character::has_enough_anesth( const itype &cbm ) const { - if( has_bionic( bio_painkiller ) || has_trait( trait_NOPAIN ) || + if( has_bionic( bio_painkiller ) || has_flag( json_flag_PAIN_IMMUNE ) || has_trait( trait_DEBUG_BIONICS ) ) { return true; } @@ -2569,7 +2569,7 @@ void Character::bionics_install_failure( const bionic_id &bid, const std::string switch( fail_type ) { case 1: - if( !has_trait( trait_NOPAIN ) ) { + if( !has_flag( json_flag_PAIN_IMMUNE ) ) { add_msg_if_player( m_bad, _( "It really hurts!" ) ); mod_pain( rng( 10, 30 ) ); } diff --git a/src/character.cpp b/src/character.cpp index 2148d8f0f8065..d3ba5637b3607 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -315,6 +315,7 @@ static const json_character_flag json_flag_NON_THRESH( "NON_THRESH" ); static const json_character_flag json_flag_NO_DISEASE( "NO_DISEASE" ); static const json_character_flag json_flag_NO_RADIATION( "NO_RADIATION" ); static const json_character_flag json_flag_NO_THIRST( "NO_THIRST" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); static const json_character_flag json_flag_PRED2( "PRED2" ); static const json_character_flag json_flag_PRED3( "PRED3" ); static const json_character_flag json_flag_PRED4( "PRED4" ); @@ -437,7 +438,6 @@ static const trait_id trait_NIGHTVISION3( "NIGHTVISION3" ); static const trait_id trait_NOMAD( "NOMAD" ); static const trait_id trait_NOMAD2( "NOMAD2" ); static const trait_id trait_NOMAD3( "NOMAD3" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_PACIFIST( "PACIFIST" ); static const trait_id trait_PADDED_FEET( "PADDED_FEET" ); static const trait_id trait_PARAIMMUNE( "PARAIMMUNE" ); @@ -4662,7 +4662,7 @@ void Character::update_needs( int rate_multiplier ) // Huge folks take penalties for cramming themselves in vehicles if( in_vehicle && get_size() == creature_size::huge && - !( has_trait( trait_NOPAIN ) || has_effect( effect_narcosis ) ) ) { + !( has_flag( json_flag_PAIN_IMMUNE ) || has_effect( effect_narcosis ) ) ) { vehicle *veh = veh_pointer_or_null( get_map().veh_at( pos() ) ); // it's painful to work the controls, but passengers in open topped vehicles are fine if( veh && ( veh->enclosed_at( pos() ) || veh->player_in_control( *this ) ) ) { @@ -4806,7 +4806,7 @@ void Character::check_needs_extremes() get_event_bus().send( getID(), efftype_id() ); set_part_hp_cur( body_part_torso, 0 ); } else if( has_effect( effect_jetinjector ) && get_effect_dur( effect_jetinjector ) > 40_minutes ) { - if( !has_trait( trait_NOPAIN ) ) { + if( !has_flag( json_flag_PAIN_IMMUNE ) ) { add_msg_player_or_npc( m_bad, _( "Your heart spasms painfully and stops." ), _( "'s heart spasms painfully and stops." ) ); @@ -5806,6 +5806,7 @@ float calc_mutation_value_multiplicative( const std::vector )>> mutation_value_map = { { "healing_awake", calc_mutation_value<&mutation_branch::healing_awake> }, + { "pain_modifier", calc_mutation_value<&mutation_branch::pain_modifier> }, { "healing_multiplier", calc_mutation_value_multiplicative<&mutation_branch::healing_multiplier> }, { "mending_modifier", calc_mutation_value_multiplicative<&mutation_branch::mending_modifier> }, { "hp_modifier", calc_mutation_value<&mutation_branch::hp_modifier> }, @@ -11160,7 +11161,7 @@ void Character::mod_pain( int npain ) { if( npain > 0 ) { double mult = enchantment_cache->get_value_multiply( enchant_vals::mod::PAIN ); - if( has_trait( trait_NOPAIN ) || has_effect( effect_narcosis ) ) { + if( has_flag( json_flag_PAIN_IMMUNE ) || has_effect( effect_narcosis ) ) { return; } // if there is a positive multiplier we always want to add at least 1 pain @@ -11170,6 +11171,12 @@ void Character::mod_pain( int npain ) if( mult < 0 ) { npain = roll_remainder( npain * ( 1 + mult ) ); } + if( mutation_value( "pain_modifier" ) != 0 ) { + npain = roll_remainder( npain + mutation_value( "pain_modifier" ) ); + if( npain < 0 ) { + return; + } + } npain += enchantment_cache->get_value_add( enchant_vals::mod::PAIN ); // no matter how powerful the enchantment if we are gaining pain we always gain at least a little/don't lose any diff --git a/src/character_body.cpp b/src/character_body.cpp index 826f109aa0229..e6a1b866baf4c 100644 --- a/src/character_body.cpp +++ b/src/character_body.cpp @@ -62,6 +62,7 @@ static const json_character_flag json_flag_HEAT_IMMUNE( "HEAT_IMMUNE" ); static const json_character_flag json_flag_IGNORE_TEMP( "IGNORE_TEMP" ); static const json_character_flag json_flag_LIMB_LOWER( "LIMB_LOWER" ); static const json_character_flag json_flag_NO_THIRST( "NO_THIRST" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); static const trait_id trait_BARK( "BARK" ); static const trait_id trait_CHITIN_FUR( "CHITIN_FUR" ); @@ -74,7 +75,6 @@ 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_M_DEPENDENT( "M_DEPENDENT" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_PYROMANIA( "PYROMANIA" ); static const trait_id trait_SLIMY( "SLIMY" ); static const trait_id trait_URSINE_FUR( "URSINE_FUR" ); @@ -1100,7 +1100,7 @@ bodypart_id Character::body_window( const std::string &menu_header, // If this is an NPC, the player is the one examining them and so the fact // that they can't self-diagnose effectively doesn't matter - bool no_feeling = is_avatar() && has_trait( trait_NOPAIN ); + bool no_feeling = is_avatar() && has_flag( json_flag_PAIN_IMMUNE ); for( size_t i = 0; i < parts.size(); i++ ) { const healable_bp &e = parts[i]; diff --git a/src/flag.cpp b/src/flag.cpp index d54960af76116..412ee9de2a89a 100644 --- a/src/flag.cpp +++ b/src/flag.cpp @@ -228,6 +228,7 @@ const flag_id flag_ORGANIC( "ORGANIC" ); const flag_id flag_OUTER( "OUTER" ); const flag_id flag_OVERSIZE( "OVERSIZE" ); const flag_id flag_PADDED( "PADDED" ); +const flag_id flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); const flag_id flag_PALS_LARGE( "PALS_LARGE" ); const flag_id flag_PALS_MEDIUM( "PALS_MEDIUM" ); const flag_id flag_PALS_SMALL( "PALS_SMALL" ); diff --git a/src/flag.h b/src/flag.h index a3f566f460acb..54b454ea4dde0 100644 --- a/src/flag.h +++ b/src/flag.h @@ -234,6 +234,7 @@ extern const flag_id flag_ORGANIC; extern const flag_id flag_OUTER; extern const flag_id flag_OVERSIZE; extern const flag_id flag_PADDED; +extern const flag_id flag_PAIN_IMMUNE; extern const flag_id flag_PALS_SMALL; extern const flag_id flag_PALS_MEDIUM; extern const flag_id flag_PALS_LARGE; diff --git a/src/game_inventory.cpp b/src/game_inventory.cpp index 9274faf5e5d7d..f49a32719f5a0 100644 --- a/src/game_inventory.cpp +++ b/src/game_inventory.cpp @@ -73,12 +73,13 @@ static const flag_id json_flag_CALORIES_INTAKE( "CALORIES_INTAKE" ); static const itype_id itype_fitness_band( "fitness_band" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); + static const quality_id qual_ANESTHESIA( "ANESTHESIA" ); static const requirement_id requirement_data_anesthetic( "anesthetic" ); static const trait_id trait_DEBUG_BIONICS( "DEBUG_BIONICS" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_SAPROPHAGE( "SAPROPHAGE" ); static const trait_id trait_SAPROVORE( "SAPROVORE" ); @@ -2231,7 +2232,7 @@ static item_location autodoc_internal( Character &you, Character &patient, int drug_count = 0; if( !surgeon ) {//surgeon use their own anesthetic, player just need money - if( patient.has_trait( trait_NOPAIN ) ) { + if( patient.has_flag( json_flag_PAIN_IMMUNE ) ) { hint = _( "Patient has deadened nerves. Anesthesia unneeded." ); } else if( patient.has_bionic( bio_painkiller ) ) { hint = _( "Patient has Sensory Dulling CBM installed. Anesthesia unneeded." ); diff --git a/src/iexamine.cpp b/src/iexamine.cpp index 31a804da3f58c..b60ccc406a5b0 100644 --- a/src/iexamine.cpp +++ b/src/iexamine.cpp @@ -178,6 +178,7 @@ static const itype_id itype_unfinished_cac2( "unfinished_cac2" ); static const itype_id itype_unfinished_charcoal( "unfinished_charcoal" ); static const json_character_flag json_flag_ATTUNEMENT( "ATTUNEMENT" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); static const json_character_flag json_flag_SUPER_HEARING( "SUPER_HEARING" ); static const json_character_flag json_flag_WALL_CLING( "WALL_CLING" ); @@ -237,7 +238,6 @@ static const trait_id trait_M_DEFENDER( "M_DEFENDER" ); static const trait_id trait_M_DEPENDENT( "M_DEPENDENT" ); static const trait_id trait_M_FERTILE( "M_FERTILE" ); static const trait_id trait_M_SPORES( "M_SPORES" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_PROBOSCIS( "PROBOSCIS" ); static const trait_id trait_PYROMANIA( "PYROMANIA" ); static const trait_id trait_SHELL2( "SHELL2" ); @@ -5174,7 +5174,7 @@ void iexamine::autodoc( Character &you, const tripoint &examp ) bool needs_anesthesia = true; std::vector anesth_kit; - if( patient.has_trait( trait_NOPAIN ) || patient.has_bionic( bio_painkiller ) || + if( patient.has_flag( json_flag_PAIN_IMMUNE ) || patient.has_bionic( bio_painkiller ) || amenu.ret > 1 ) { needs_anesthesia = false; } else { diff --git a/src/iuse.cpp b/src/iuse.cpp index 0b82341bb0247..f8b47070d3f33 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -314,6 +314,7 @@ static const json_character_flag json_flag_ENHANCED_VISION( "ENHANCED_VISION" ); static const json_character_flag json_flag_HYPEROPIC( "HYPEROPIC" ); static const json_character_flag json_flag_MYOPIC( "MYOPIC" ); static const json_character_flag json_flag_MYOPIC_IN_LIGHT( "MYOPIC_IN_LIGHT" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); static const mongroup_id GROUP_FISH( "GROUP_FISH" ); @@ -377,7 +378,6 @@ static const trait_id trait_MARLOSS_AVOID( "MARLOSS_AVOID" ); static const trait_id trait_MARLOSS_BLUE( "MARLOSS_BLUE" ); static const trait_id trait_MARLOSS_YELLOW( "MARLOSS_YELLOW" ); static const trait_id trait_M_DEPENDENT( "M_DEPENDENT" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_PSYCHOPATH( "PSYCHOPATH" ); static const trait_id trait_PYROMANIA( "PYROMANIA" ); static const trait_id trait_SPIRITUAL( "SPIRITUAL" ); @@ -769,7 +769,7 @@ std::optional iuse::antiparasitic( Character *p, item *, bool, const tripoi if( p->has_effect( effect_tapeworm ) ) { p->remove_effect( effect_tapeworm ); p->guts.mod_nutr( -1 ); // You just digested the tapeworm. - if( p->has_trait( trait_NOPAIN ) ) { + if( p->has_flag( json_flag_PAIN_IMMUNE ) ) { p->add_msg_if_player( m_good, _( "Your bowels clench as something inside them dies." ) ); } else { p->add_msg_if_player( m_mixed, _( "Your bowels spasm painfully as something inside them dies." ) ); @@ -786,7 +786,7 @@ std::optional iuse::antiparasitic( Character *p, item *, bool, const tripoi } if( p->has_effect( effect_brainworms ) ) { p->remove_effect( effect_brainworms ); - if( p->has_trait( trait_NOPAIN ) ) { + if( p->has_flag( json_flag_PAIN_IMMUNE ) ) { p->add_msg_if_player( m_good, _( "The pressure inside your head feels better already." ) ); } else { p->add_msg_if_player( m_mixed, @@ -796,7 +796,7 @@ std::optional iuse::antiparasitic( Character *p, item *, bool, const tripoi } if( p->has_effect( effect_paincysts ) ) { p->remove_effect( effect_paincysts ); - if( p->has_trait( trait_NOPAIN ) ) { + if( p->has_flag( json_flag_PAIN_IMMUNE ) ) { p->add_msg_if_player( m_good, _( "The stiffness in your joints goes away." ) ); } else { p->add_msg_if_player( m_good, _( "The pain in your joints goes away." ) ); diff --git a/src/medical_ui.cpp b/src/medical_ui.cpp index 870b1f123deb2..021cd60174090 100644 --- a/src/medical_ui.cpp +++ b/src/medical_ui.cpp @@ -27,8 +27,8 @@ static const efftype_id effect_infected( "infected" ); static const efftype_id effect_mending( "mending" ); static const json_character_flag json_flag_ECTOTHERM( "ECTOTHERM" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_SUNLIGHT_DEPENDENT( "SUNLIGHT_DEPENDENT" ); static const trait_id trait_TROGLO( "TROGLO" ); static const trait_id trait_TROGLO2( "TROGLO2" ); @@ -353,7 +353,7 @@ static medical_column draw_health_summary( const int column_count, avatar *playe const bool bleeding = bleed_intensity > 0; const bool bitten = player->has_effect( effect_bite, part.id() ); const bool infected = player->has_effect( effect_infected, part.id() ); - const bool no_feeling = player->has_trait( trait_NOPAIN ); + const bool no_feeling = player->has_flag( json_flag_PAIN_IMMUNE ); const int maximal_hp = player->get_part_hp_max( part ); const int current_hp = player->get_part_hp_cur( part ); const bool limb_is_broken = player->is_limb_broken( part ); diff --git a/src/mutation.h b/src/mutation.h index 5e20e60cabc1b..899d658001c8f 100644 --- a/src/mutation.h +++ b/src/mutation.h @@ -204,6 +204,7 @@ struct mutation_branch { std::optional healing_multiplier = std::nullopt; // Limb mending bonus std::optional mending_modifier = std::nullopt; + std::optional pain_modifier = std::nullopt; // Bonus HP multiplier. That is, 1.0 doubles hp, -0.5 halves it. std::optional hp_modifier = std::nullopt; // Second HP modifier that stacks with first but is otherwise identical. diff --git a/src/mutation_data.cpp b/src/mutation_data.cpp index e5deafec8ea9a..e56e8bb270c60 100644 --- a/src/mutation_data.cpp +++ b/src/mutation_data.cpp @@ -387,6 +387,7 @@ void mutation_branch::load( const JsonObject &jo, const std::string &src ) } optional( jo, was_loaded, "healing_awake", healing_awake, std::nullopt ); + optional( jo, was_loaded, "pain_modifier", pain_modifier, std::nullopt ); optional( jo, was_loaded, "healing_multiplier", healing_multiplier, std::nullopt ); optional( jo, was_loaded, "mending_modifier", mending_modifier, std::nullopt ); optional( jo, was_loaded, "hp_modifier", hp_modifier, std::nullopt ); diff --git a/src/player_hardcoded_effects.cpp b/src/player_hardcoded_effects.cpp index ca8455c23c633..3fd19b9e8d42b 100644 --- a/src/player_hardcoded_effects.cpp +++ b/src/player_hardcoded_effects.cpp @@ -102,6 +102,7 @@ static const efftype_id effect_weak_antibiotic( "weak_antibiotic" ); static const efftype_id effect_winded( "winded" ); static const json_character_flag json_flag_ALARMCLOCK( "ALARMCLOCK" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); static const json_character_flag json_flag_SEESLEEP( "SEESLEEP" ); static const mongroup_id GROUP_NETHER( "GROUP_NETHER" ); @@ -123,7 +124,6 @@ static const trait_id trait_HIBERNATE( "HIBERNATE" ); static const trait_id trait_INFRESIST( "INFRESIST" ); static const trait_id trait_M_IMMUNE( "M_IMMUNE" ); static const trait_id trait_M_SKIN3( "M_SKIN3" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_SCHIZOPHRENIC( "SCHIZOPHRENIC" ); static const trait_id trait_THRESH_MYCUS( "THRESH_MYCUS" ); static const trait_id trait_WATERSLEEP( "WATERSLEEP" ); @@ -721,7 +721,7 @@ static void eff_fun_datura( Character &u, effect &it ) } if( dur > 1800_minutes && one_in( 300 * 512 ) ) { - if( !u.has_trait( trait_NOPAIN ) ) { + if( !u.has_flag( json_flag_PAIN_IMMUNE ) ) { u.add_msg_if_player( m_bad, _( "Your heart spasms painfully and stops, dragging you back to reality as you die." ) ); } else { diff --git a/src/sounds.cpp b/src/sounds.cpp index 91f1eb5cff082..5d49820dbffb9 100644 --- a/src/sounds.cpp +++ b/src/sounds.cpp @@ -91,6 +91,8 @@ static const itype_id fuel_type_muscle( "muscle" ); static const itype_id fuel_type_wind( "wind" ); static const itype_id itype_weapon_fire_suppressed( "weapon_fire_suppressed" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); + static const material_id material_bone( "bone" ); static const material_id material_flesh( "flesh" ); static const material_id material_hflesh( "hflesh" ); @@ -179,7 +181,6 @@ static const ter_str_id ter_t_underbrush_harvested_winter( "t_underbrush_harvest static const trait_id trait_HEAVYSLEEPER( "HEAVYSLEEPER" ); static const trait_id trait_HEAVYSLEEPER2( "HEAVYSLEEPER2" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); struct monster_sound_event { int volume; @@ -561,7 +562,7 @@ void sounds::process_sound_markers( Character *you ) if( is_sound_deafening && !you->is_immune_effect( effect_deaf ) ) { you->add_effect( effect_deaf, std::min( 4_minutes, time_duration::from_turns( felt_volume - 130 ) / 8 ) ); - if( !you->has_trait( trait_NOPAIN ) ) { + if( !you->has_flag( json_flag_PAIN_IMMUNE ) ) { you->add_msg_if_player( m_bad, _( "Your eardrums suddenly ache!" ) ); if( you->get_pain() < 10 ) { you->mod_pain( rng( 0, 2 ) ); diff --git a/src/suffer.cpp b/src/suffer.cpp index b8af1098d131f..8bbb3a34d0b7f 100644 --- a/src/suffer.cpp +++ b/src/suffer.cpp @@ -123,6 +123,7 @@ static const json_character_flag json_flag_GLARE_RESIST( "GLARE_RESIST" ); static const json_character_flag json_flag_MEND_ALL( "MEND_ALL" ); static const json_character_flag json_flag_MEND_LIMB( "MEND_LIMB" ); static const json_character_flag json_flag_NYCTOPHOBIA( "NYCTOPHOBIA" ); +static const json_character_flag json_flag_PAIN_IMMUNE( "PAIN_IMMUNE" ); static const json_character_flag json_flag_RAD_DETECT( "RAD_DETECT" ); static const mtype_id mon_zombie( "mon_zombie" ); @@ -151,7 +152,6 @@ static const trait_id trait_M_BLOSSOMS( "M_BLOSSOMS" ); static const trait_id trait_M_SPORES( "M_SPORES" ); static const trait_id trait_NARCOLEPTIC( "NARCOLEPTIC" ); static const trait_id trait_NONADDICTIVE( "NONADDICTIVE" ); -static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_PER_SLIME( "PER_SLIME" ); static const trait_id trait_PYROMANIA( "PYROMANIA" ); static const trait_id trait_RADIOACTIVE1( "RADIOACTIVE1" ); @@ -464,7 +464,7 @@ void suffer::while_awake( Character &you, const int current_stim ) void suffer::from_chemimbalance( Character &you ) { - if( one_turn_in( 6_hours ) && !you.has_trait( trait_NOPAIN ) ) { + if( one_turn_in( 6_hours ) && !you.has_flag( json_flag_PAIN_IMMUNE ) ) { you.add_msg_if_player( m_bad, _( "You suddenly feel sharp pain for no reason." ) ); you.mod_pain( 3 * rng( 1, 3 ) ); } @@ -472,7 +472,7 @@ void suffer::from_chemimbalance( Character &you ) int pkilladd = 5 * rng( -1, 2 ); if( pkilladd > 0 ) { you.add_msg_if_player( m_bad, _( "You suddenly feel numb." ) ); - } else if( ( pkilladd < 0 ) && ( !you.has_trait( trait_NOPAIN ) ) ) { + } else if( ( pkilladd < 0 ) && ( !you.has_flag( json_flag_PAIN_IMMUNE ) ) ) { you.add_msg_if_player( m_bad, _( "You suddenly ache." ) ); } you.mod_painkiller( pkilladd ); @@ -1377,7 +1377,7 @@ void suffer::from_bad_bionics( Character &you ) if( you.has_bionic( bio_dis_shock ) && you.get_power_level() > bio_dis_shock->power_trigger && one_turn_in( 2_hours ) && !you.has_effect( effect_narcosis ) ) { - if( !you.has_trait( trait_NOPAIN ) ) { + if( !you.has_flag( json_flag_PAIN_IMMUNE ) ) { you.add_msg_if_player( m_bad, _( "You suffer a painful electrical discharge!" ) ); you.mod_pain( 1 ); } else { @@ -1399,7 +1399,7 @@ void suffer::from_bad_bionics( Character &you ) sfx::play_variant_sound( "bionics", "elec_discharge", 100 ); } if( you.has_bionic( bio_dis_acid ) && one_turn_in( 150_minutes ) ) { - if( !you.has_trait( trait_NOPAIN ) ) { + if( !you.has_flag( json_flag_PAIN_IMMUNE ) ) { you.add_msg_if_player( m_bad, _( "You suffer a burning acidic discharge!" ) ); } else { you.add_msg_if_player( m_bad, _( "You experience an acidic discharge!" ) );