From 9a6214bec44f708201b536bdd05e64d7a1816323 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Mon, 1 Mar 2021 16:38:12 -0800 Subject: [PATCH] Allow mutations to prevent installing CBMs Bionics can currently cancel mutations when installed, but can't have mutations prevent installation. --- doc/JSON_INFO.md | 2 ++ src/bionics.cpp | 8 ++++++++ src/bionics.h | 4 ++++ src/mutation.cpp | 12 ++++++++++++ 4 files changed, 26 insertions(+) diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index 42002388737d3..9710a257f94bc 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -655,6 +655,7 @@ For information about tools with option to export ASCII art in format ready to b | weight_capacity_bonus | (_optional_) Bonus to weight carrying capacity in grams, can be negative. Strings can be used - "5000 g" or "5 kg" (default: `0`) | weight_capacity_modifier | (_optional_) Factor modifying base weight carrying capacity. (default: `1`) | canceled_mutations | (_optional_) A list of mutations/traits that are removed when this bionic is installed (e.g. because it replaces the fault biological part). +| mutation_conflicts | (_optional_) A list of mutations that prevent this bionic from being installed. | included_bionics | (_optional_) Additional bionics that are installed automatically when this bionic is installed. This can be used to install several bionics from one CBM item, which is useful as each of those can be activated independently. | included | (_optional_) Whether this bionic is included with another. If true this bionic does not require a CBM item to be defined. (default: `false`) | env_protec | (_optional_) How much environmental protection does this bionic provide on the specified body parts. @@ -692,6 +693,7 @@ For information about tools with option to export ASCII art in format ready to b "encumbrance" : [ [ "torso", 10 ], [ "arm_l", 10 ], [ "arm_r", 10 ], [ "leg_l", 10 ], [ "leg_r", 10 ], [ "foot_l", 10 ], [ "foot_r", 10 ] ], "description" : "You have a battery draining attachment, and thus can make use of the energy contained in normal, everyday batteries. Use 'E' to consume batteries.", "canceled_mutations": ["HYPEROPIC"], + "mutation_conflicts": [ "HUGE" ], "installation_requirement": "sewing_standard", "included_bionics": ["bio_blindfold"] }, diff --git a/src/bionics.cpp b/src/bionics.cpp index b297a1a96c557..a2385a19904dd 100644 --- a/src/bionics.cpp +++ b/src/bionics.cpp @@ -318,6 +318,7 @@ void bionic_data::load( const JsonObject &jsobj, const std::string & ) optional( jsobj, was_loaded, "learned_spells", learned_spells ); optional( jsobj, was_loaded, "learned_proficiencies", proficiencies ); optional( jsobj, was_loaded, "canceled_mutations", canceled_mutations ); + optional( jsobj, was_loaded, "mutation_conflicts", mutation_conflicts ); optional( jsobj, was_loaded, "included_bionics", included_bionics ); optional( jsobj, was_loaded, "included", included ); optional( jsobj, was_loaded, "upgraded_bionic", upgraded_bionic ); @@ -2324,6 +2325,10 @@ ret_val Character::is_installable( const item_location &loc, const bool by const itype *itemtype = it->type; const bionic_id &bid = itemtype->bionic->id; + const auto has_trait_lambda = [this]( const trait_id & candidate ) { + return has_trait( candidate ); + }; + if( it->has_flag( flag_FILTHY ) ) { // NOLINTNEXTLINE(cata-text-style): single space after the period for symmetry const std::string msg = by_autodoc ? _( "/!\\ CBM is highly contaminated. /!\\" ) : @@ -2341,6 +2346,9 @@ ret_val Character::is_installable( const item_location &loc, const bool by return ret_val::make_failure( _( "CBM is already installed." ) ); } else if( !can_install_cbm_on_bp( get_occupied_bodyparts( bid ) ) ) { return ret_val::make_failure( _( "CBM not compatible with patient's body." ) ); + } else if( std::any_of( bid->mutation_conflicts.begin(), bid->mutation_conflicts.end(), + has_trait_lambda ) ) { + return ret_val::make_failure( _( "CBM not compatible with patient's body." ) ); } else if( bid->upgraded_bionic && !has_bionic( bid->upgraded_bionic ) && it->is_upgrade() ) { diff --git a/src/bionics.h b/src/bionics.h index 8f18e22307110..0dfee95903409 100644 --- a/src/bionics.h +++ b/src/bionics.h @@ -113,6 +113,10 @@ struct bionic_data { * E.g. enhanced optic bionic may cancel HYPEROPIC trait. */ std::vector canceled_mutations; + /** + * Mutations/traits that prevent installing this CBM + */ + std::set mutation_conflicts; /** * The spells you learn when you install this bionic, and what level you learn them at. diff --git a/src/mutation.cpp b/src/mutation.cpp index ea289fdce0c25..64fb3a39c8b14 100644 --- a/src/mutation.cpp +++ b/src/mutation.cpp @@ -856,6 +856,10 @@ bool Character::mutation_ok( const trait_id &mutation, bool force_good, bool for return false; } } + + if( bid->mutation_conflicts.count( mutation ) != 0 ) { + return false; + } } const mutation_branch &mdata = mutation.obj(); @@ -1184,6 +1188,14 @@ bool Character::mutate_towards( const trait_id &mut ) return false; } + // Just prevent it when it conflicts with a CBM, for now + // TODO: Consequences? + for( const bionic_id &bid : get_bionics() ) { + if( bid->mutation_conflicts.count( mut ) != 0 ) { + return false; + } + } + for( size_t i = 0; !has_threshreq && i < threshreq.size(); i++ ) { if( has_trait( threshreq[i] ) ) { has_threshreq = true;