diff --git a/data/json/bionics.json b/data/json/bionics.json index e6008da202e5..913ca83862aa 100644 --- a/data/json/bionics.json +++ b/data/json/bionics.json @@ -526,7 +526,8 @@ "flags": [ "BIONIC_TOGGLED", "BIONIC_NPC_USABLE" ], "act_cost": "10 kJ", "react_cost": "10 kJ", - "time": 1 + "time": 1, + "required_bionic": "bio_weight" }, { "id": "bio_infolink", diff --git a/data/json/professions.json b/data/json/professions.json index ed16053d4dad..f04cf9003dbb 100644 --- a/data/json/professions.json +++ b/data/json/professions.json @@ -2353,6 +2353,7 @@ "bio_tools", "bio_sunglasses", "bio_flashlight", + "bio_weight", "bio_hydraulics", "bio_cable", "bio_power_storage_mkII", @@ -2381,7 +2382,7 @@ "name": "Bionic Athlete", "description": "It's a shame the apocalypse happened; you'll never get a shot at the Cyberolympics. Now the only thing between you and death by zombie is your freakish cyborg strength.", "points": 5, - "CBMs": [ "bio_str_enhancer", "bio_adrenaline", "bio_hydraulics", "bio_metabolics", "bio_power_storage_mkII" ], + "CBMs": [ "bio_str_enhancer", "bio_weight", "bio_adrenaline", "bio_hydraulics", "bio_metabolics", "bio_power_storage_mkII" ], "items": { "both": [ "socks_ankle", @@ -5407,6 +5408,7 @@ "bio_power_storage_mkII", "bio_claws", "bio_digestion", + "bio_weight", "bio_hydraulics" ], "skills": [ diff --git a/doc/src/content/docs/en/mod/json/reference/json_info.md b/doc/src/content/docs/en/mod/json/reference/json_info.md index 5f39aa45b31c..2bdb11055deb 100644 --- a/doc/src/content/docs/en/mod/json/reference/json_info.md +++ b/doc/src/content/docs/en/mod/json/reference/json_info.md @@ -188,43 +188,55 @@ the appropriate JSON file. ### Bionics -| Identifier | Description | -| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| id | (_mandatory_) Unique ID. Must be one continuous word, use underscores if necessary. | -| name | (_mandatory_) In-game name displayed. | -| description | (_mandatory_) In-game description. | -| flags | (_optional_) A list of flags. See JSON_FLAGS.md for supported values. | -| act_cost | (_optional_) How many kJ it costs to activate the bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | -| deact_cost | (_optional_) How many kJ it costs to deactivate the bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | -| react_cost | (_optional_) How many kJ it costs over time to keep this bionic active, does nothing without a non-zero "time". Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | -| time | (_optional_) How long, when activated, between drawing cost. If 0, it draws power once. (default: `0`) | -| upgraded_bionic | (_optional_) Bionic that can be upgraded by installing this one. | -| available_upgrades | (_optional_) Upgrades available for this bionic, i.e. the list of bionics having this one referenced by `upgraded_bionic`. | -| encumbrance | (_optional_) A list of body parts and how much this bionic encumber them. | -| 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). | -| 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. | -| bash_protec | (_optional_) How much bash protection does this bionic provide on the specified body parts. | -| cut_protec | (_optional_) How much cut protection does this bionic provide on the specified body parts. | -| bullet_protect | (_optional_) How much bullet protect does this bionic provide on the specified body parts. | -| occupied_bodyparts | (_optional_) A list of body parts occupied by this bionic, and the number of bionic slots it take on those parts. | -| capacity | (_optional_) Amount of power storage added by this bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | -| fuel_options | (_optional_) A list of fuel that this bionic can use to produce bionic power. | -| is_remote_fueled | (_optional_) If true this bionic allows you to plug your power banks to an external power source (solar backpack, UPS, vehicle etc) via a cable. (default: `false`) | -| fuel_capacity | (_optional_) Volume of fuel this bionic can store. | -| fuel_efficiency | (_optional_) Fraction of fuel energy converted into power. (default: `0`) | -| fuel_multiplier | (_optional_) Multiplies the amount of fuel when loading into the bionic (default: `1`) | -| passive_fuel_efficiency | (_optional_) Fraction of fuel energy passively converted into power. Useful for CBM using PERPETUAL fuel like `muscle`, `wind` or `sun_light`. (default: `0`) | -| exothermic_power_gen | (_optional_) If true this bionic emits heat when producing power. (default: `false`) | -| coverage_power_gen_penalty | (_optional_) Fraction of coverage diminishing fuel_efficiency. Float between 0.0 and 1.0. (default: `nullopt`) | -| power_gen_emission | (_optional_) `emit_id` of the field emitted by this bionic when it produces energy. Emit_ids are defined in `emit.json`. | -| stat_bonus | (_optional_) List of passive stat bonus. Stat are designated as follow: "DEX", "INT", "STR", "PER". | -| enchantments | (_optional_) List of enchantments applied by this CBM (see MAGIC.md for instructions on enchantment. NB: enchantments are not necessarily magic.) | -| learned_spells | (_optional_) List of spells (with levels) you gain when installing this CBM, and lose when you uninstall this CBM. Spell classes are automatically gained. | -| fake_item | (_optional_) ID of fake item used by this bionic. Mandatory for gun and weapon bionics. | +| Identifier | Description | +| ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| id | (_mandatory_) Unique ID. Must be one continuous word, use underscores if necessary. | +| name | (_mandatory_) In-game name displayed. | +| description | (_mandatory_) In-game description. | +| flags | (_optional_) A list of flags. See JSON_FLAGS.md for supported values. | +| act_cost | (_optional_) How many kJ it costs to activate the bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | +| deact_cost | (_optional_) How many kJ it costs to deactivate the bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | +| react_cost | (_optional_) How many kJ it costs over time to keep this bionic active, does nothing without a non-zero "time". Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | +| time | (_optional_) How long, when activated, between drawing cost. If 0, it draws power once. (default: `0`) | +| upgraded_bionic | (_optional_) Bionic that can be upgraded by installing this one. | +| required_bionic | (_optional_) Bionic which is required to install this bionic, and which cannot be uninstalled if this bionic is installed | +| available_upgrades | (_optional_) Upgrades available for this bionic, i.e. the list of bionics | +| having this one referenced by `upgraded_bionic`. | | +| and how much this bionic encumber them. | | +| carrying capacity in grams, can be negative. Strings can be used - "5000 g" or "5 kg" (default: `0`) | | +| | weight_capacity_modifier | +| (default: `1`) | | +| when this bionic is installed (e.g. because it replaces the fault biological part). | | +| 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. | | +| 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. | | +| provide on the specified body parts. | | +| bionic provide on the specified body parts. | | +| protect does this bionic provide on the specified body parts. | | +| A list of body parts occupied by this bionic, and the number of bionic slots it take on those parts. | | +| | capacity | +| kJ"/"1000 J"/"1000000 mJ" (default: `0`) | | +| bionic can use to produce bionic power. | | +| allows you to plug your power banks to an external power source (solar backpack, UPS, vehicle etc) | | +| via a cable. (default: `false`) | | +| store. | | +| `0`) | | +| (default: `1`) | | +| converted into power. Useful for CBM using PERPETUAL fuel like `muscle`, `wind` or `sun_light`. | | +| (default: `0`) | | +| power. (default: `false`) | | +| diminishing fuel_efficiency. Float between 0.0 and 1.0. (default: `nullopt`) | | +| (_optional_) `emit_id` of the field emitted by this bionic when it produces energy. Emit_ids are | | +| defined in `emit.json`. | | +| designated as follow: "DEX", "INT", "STR", "PER". | | +| enchantments applied by this CBM (see MAGIC.md for instructions on enchantment. NB: enchantments are | | +| not necessarily magic.) | | +| installing this CBM, and lose when you uninstall this CBM. Spell classes are automatically gained. | | +| fake_item | (_optional_) ID of fake item used by this bionic. Mandatory for gun and weapon | +| bionics. | | ```json { diff --git a/src/bionics.cpp b/src/bionics.cpp index 3fdf8473a66d..4d31700f3aca 100644 --- a/src/bionics.cpp +++ b/src/bionics.cpp @@ -313,6 +313,7 @@ void bionic_data::load( const JsonObject &jsobj, const std::string &src ) assign( jsobj, "enchantments", enchantments, strict ); assign_map_from_array( jsobj, "learned_spells", learned_spells, strict ); assign( jsobj, "included_bionics", included_bionics, strict ); + assign( jsobj, "required_bionic", required_bionic, strict ); assign( jsobj, "upgraded_bionic", upgraded_bionic, strict ); assign( jsobj, "available_upgrades", available_upgrades, strict ); assign( jsobj, "flags", flags, strict ); @@ -410,6 +411,14 @@ void bionic_data::check() const rep.warn( "upgrades undefined bionic \"%s\"", upgraded_bionic.str() ); } } + if( required_bionic ) { + if( required_bionic == id ) { + rep.warn( "The CBM %s requires itself as a prerequisite for installation", required_bionic.str() ); + } else if( !required_bionic.is_valid() ) { + rep.warn( "The CBM %s requires undefined bionic %s", id.str(), required_bionic.str() ); + } + } + for( const bionic_id &it : available_upgrades ) { if( !it.is_valid() ) { rep.warn( "specifies unknown upgrade \"%s\"", it.str() ); @@ -2036,6 +2045,14 @@ bool Character::can_uninstall_bionic( const bionic_id &b_id, player &installer, } } + for( const bionic_id &bid : get_bionics() ) { + if( bid->required_bionic == b_id ) { + popup( _( "%s cannot be removed because installed bionic %s requires it." ), + b_id->name, bid->name ); + return false; + } + } + if( b_id == bio_eye_optic ) { popup( _( "The Telescopic Lenses are part of %s eyes now. Removing them would leave %s blind." ), disp_name( true ), disp_name() ); @@ -2279,6 +2296,11 @@ bool Character::can_install_bionics( const itype &type, player &installer, bool } int chance_of_success = bionic_manip_cos( adjusted_skill, difficult ); + if( bioid->required_bionic && !has_bionic( bioid->required_bionic ) ) { + popup( _( "CBM requires prior installation of %s." ), bioid->required_bionic.obj().name ); + return false; + } + std::vector conflicting_muts; for( const trait_id &mid : bioid->canceled_mutations ) { if( has_trait( mid ) ) { diff --git a/src/bionics.h b/src/bionics.h index 78208bfb99c5..a3a478383162 100644 --- a/src/bionics.h +++ b/src/bionics.h @@ -134,6 +134,11 @@ struct bionic_data { * Upgrades available for this bionic (opposite to @ref upgraded_bionic). */ std::set available_upgrades; + /** + * Id of another bionic which this bionic needs to have installed to be installed. + * Also prevents that bionic from being removed while this bionic is installed. + */ + bionic_id required_bionic; std::set flags; bool has_flag( const flag_id &flag ) const; diff --git a/src/item.cpp b/src/item.cpp index 6daf7c5bd204..5ff414d5dc93 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -3382,6 +3382,13 @@ void item::bionic_info( std::vector &info, const iteminfo_query *parts insert_separation_line( info ); + if( bid->required_bionic ) { + info.emplace_back( "CBM", string_format( "* This CBM requires another CBM to also be installed: %s", + bid->required_bionic->name ) ); + } + + insert_separation_line( info ); + if( !bid->encumbrance.empty() ) { info.emplace_back( "DESCRIPTION", _( "Encumbrance: " ), iteminfo::no_newline );