From e88886723bb5af442054091bec0ee84bc39142ce Mon Sep 17 00:00:00 2001 From: Fris0uman <41293484+Fris0uman@users.noreply.github.com> Date: Thu, 22 Aug 2019 18:57:33 +0200 Subject: [PATCH] Jsonize Weight capacity modifier for armor and CBM (#33394) --- data/json/bionics.json | 1 + doc/JSON_INFO.md | 44 ++++++++++--------- src/bionics.cpp | 9 ++++ src/bionics.h | 5 +++ src/character.cpp | 18 ++++++-- src/item.cpp | 99 ++++++++++++++++++++++++++++++++++++++++-- src/item.h | 10 +++++ src/item_factory.cpp | 7 +++ src/itype.h | 8 ++++ src/units.h | 5 +++ 10 files changed, 179 insertions(+), 27 deletions(-) diff --git a/data/json/bionics.json b/data/json/bionics.json index 557158893bc8e..6103a74050fbe 100644 --- a/data/json/bionics.json +++ b/data/json/bionics.json @@ -1085,6 +1085,7 @@ "name": "Titanium Skeletal Bracing", "description": "Titanium bracing has been installed onto your elbows, knees, and spine, making them far better at handling strain. Your carrying capacity is increased by 20 kilograms, or about 44 pounds.", "occupied_bodyparts": [ [ "TORSO", 8 ], [ "ARM_L", 3 ], [ "ARM_R", 3 ], [ "LEG_L", 3 ], [ "LEG_R", 3 ] ], + "weight_capacity_bonus": "20 kg", "flags": [ "BIONIC_NPC_USABLE", "BIONIC_SHOCKPROOF" ] }, { diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index 2aa51f5b341b1..2c4911e9d1fc3 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -161,26 +161,28 @@ Currently, only some JSON values support this syntax (see [here](https://github. ### Bionics -| Identifier | Description -|--- |--- -| id | Unique ID. Must be one continuous word, use underscores if necessary. -| name | In-game name displayed. -| active | Whether the bionic is active or passive. (default: `passive`) -| power_source | Whether the bionic provides power. (default: `false`) -| faulty | Whether it is a faulty type. (default: `false`) -| cost | How many PUs it costs to use the bionic. (default: `0`) -| time | How long, when activated, between drawing cost/converting fuel to power. If 0, it draws power once and never produce any in the case of a fueled bionic. (default: `0`) -| description | In-game description. -| encumbrance | (_optional_) A list of body parts and how much this bionic encumber them. -| 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. -| 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. -| fuel_options | (_optional_) A list of fuel that this bionic can use to produce bionic power. -| fuel_capacity | (_optional_) Volume of fuel this bionic can store. -| fuel_efficiency | (_optional_) Fraction of fuel energy converted into power. (default: `0`) +| Identifier | Description +|--- |--- +| id | Unique ID. Must be one continuous word, use underscores if necessary. +| name | In-game name displayed. +| active | Whether the bionic is active or passive. (default: `passive`) +| power_source | Whether the bionic provides power. (default: `false`) +| faulty | Whether it is a faulty type. (default: `false`) +| cost | How many PUs it costs to use the bionic. (default: `0`) +| time | How long, when activated, between drawing cost. If 0, it draws power once. (default: `0`) +| description | In-game description. +| 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 must 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. +| 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. +| fuel_options | (_optional_) A list of fuel that this bionic can use to produce bionic power. +| fuel_capacity | (_optional_) Volume of fuel this bionic can store. +| fuel_efficiency | (_optional_) Fraction of fuel energy converted into power. (default: `0`) ```C++ { @@ -916,6 +918,8 @@ Armor can be defined like this: "warmth" : 10, // (Optional, default = 0) How much warmth clothing provides "environmental_protection" : 0, // (Optional, default = 0) How much environmental protection it affords "encumbrance" : 0, // Base encumbrance (unfitted value) +"weight_capacity_bonus": "20 kg", // (Optional, default = 0) Bonus to weight carrying capacity, can be negative. Strings must be used - "5000 g" or "5 kg" +"weight_capacity_modifier": 1.5, // (Optional, default = 1) Factor modifying base weight carrying capacity. "coverage" : 80, // What percentage of body part "material_thickness" : 1, // Thickness of material, in millimeter units (approximately). Generally ranges between 1 - 5, more unusual armor types go up to 10 or more "power_armor" : false, // If this is a power armor item (those are special). diff --git a/src/bionics.cpp b/src/bionics.cpp index dd6a9d9a54753..0ae560ada7d4f 100644 --- a/src/bionics.cpp +++ b/src/bionics.cpp @@ -2015,6 +2015,7 @@ static bool get_bool_or_flag( JsonObject &jsobj, const std::string &name, const void load_bionic( JsonObject &jsobj ) { + bionic_data new_bionic; const bionic_id id( jsobj.get_string( "id" ) ); @@ -2052,6 +2053,14 @@ void load_bionic( JsonObject &jsobj ) new_bionic.fake_item = jsobj.get_string( "fake_item", "" ); + new_bionic.weight_capacity_modifier = jsobj.get_float( "weight_capacity_modifier", 1.0 ); + + if( jsobj.has_string( "weight_capacity_bonus" ) ) { + new_bionic.weight_capacity_bonus = read_from_json_string + ( *jsobj.get_raw( "weight_capacity_bonus" ), units::mass_units ); + } + + jsobj.read( "canceled_mutations", new_bionic.canceled_mutations ); jsobj.read( "included_bionics", new_bionic.included_bionics ); jsobj.read( "included", new_bionic.included ); diff --git a/src/bionics.h b/src/bionics.h index 9b2b9d951b2b0..e2ff94d32bc3b 100644 --- a/src/bionics.h +++ b/src/bionics.h @@ -13,6 +13,7 @@ #include "calendar.h" #include "string_id.h" #include "type_id.h" +#include "units.h" class player; class JsonObject; @@ -74,6 +75,10 @@ struct bionic_data { * If true, this bionic is included with another. */ bool included = false; + /**Factor modifiying weight capacity*/ + float weight_capacity_modifier; + /**Bonus to weight capacity*/ + units::mass weight_capacity_bonus; /**Fuel types that can be used by this bionic*/ std::vector fuel_opts; /**How much fuel this bionic can hold*/ diff --git a/src/character.cpp b/src/character.cpp index 10cd514705a8a..9c68500014254 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -1441,12 +1441,24 @@ units::mass Character::weight_capacity() const ret += get_str() * 4_kilogram; ret *= mutation_value( "weight_capacity_modifier" ); + units::mass worn_weight_bonus = 0_gram; + for( const item &it : worn ) { + ret *= it.get_weight_capacity_modifier(); + worn_weight_bonus += it.get_weight_capacity_bonus(); + } + + units::mass bio_weight_bonus = 0_gram; + for( const bionic &bio : *my_bionics ) { + ret *= bio.info().weight_capacity_modifier; + bio_weight_bonus += bio.info().weight_capacity_bonus; + } + + ret += bio_weight_bonus + worn_weight_bonus ; + if( has_artifact_with( AEP_CARRY_MORE ) ) { ret += 22500_gram; } - if( has_bionic( bionic_id( "bio_weight" ) ) ) { - ret += 20_kilogram; - } + if( ret < 0_gram ) { ret = 0_gram; } diff --git a/src/item.cpp b/src/item.cpp index 08fea9de43b20..cacb671d0fc43 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -2037,6 +2037,29 @@ std::string item::info( std::vector &info, const iteminfo_query *parts "item." ) ) ); } } + const units::mass weight_bonus = get_weight_capacity_bonus(); + const float weight_modif = get_weight_capacity_modifier(); + if( weight_modif != 1 ) { + std::string modifier; + if( weight_modif < 1 ) { + modifier = "x"; + } else { + modifier = "x"; + } + info.push_back( iteminfo( "ARMOR", + _( "Weight capacity modifier: " ), modifier, + iteminfo::no_newline | iteminfo::is_decimal, weight_modif ) ); + } + if( weight_bonus != 0_gram ) { + std::string bonus; + if( weight_bonus < 0_gram ) { + bonus = string_format( " %s", weight_units() ); + } else { + bonus = string_format( " %s", weight_units() ); + } + info.push_back( iteminfo( "ARMOR", _( "Weight capacity bonus: " ), bonus, + iteminfo::no_newline | iteminfo::is_decimal, convert_weight( weight_bonus ) ) ); + } } if( is_book() ) { @@ -2643,10 +2666,60 @@ std::string item::info( std::vector &info, const iteminfo_query *parts } // TODO: Unhide when enforcing limits - if( is_bionic() && get_option < bool >( "CBM_SLOTS_ENABLED" ) - && parts->test( iteminfo_parts::DESCRIPTION_CBM_SLOTS ) ) { - info.push_back( iteminfo( "DESCRIPTION", list_occupied_bps( type->bionic->id, - _( "This bionic is installed in the following body part(s):" ) ) ) ); + if( is_bionic() ) { + if( get_option < bool >( "CBM_SLOTS_ENABLED" ) + && parts->test( iteminfo_parts::DESCRIPTION_CBM_SLOTS ) ) { + info.push_back( iteminfo( "DESCRIPTION", list_occupied_bps( type->bionic->id, + _( "This bionic is installed in the following body part(s):" ) ) ) ); + } + insert_separation_line(); + + const bionic_id bid = type->bionic->id; + + if( !bid->encumbrance.empty() ) { + info.push_back( iteminfo( "DESCRIPTION", _( "Encumbrance: " ), + iteminfo::no_newline ) ); + for( const auto &element : bid->encumbrance ) { + info.push_back( iteminfo( "CBM", body_part_name_as_heading( element.first, 1 ), " ", + iteminfo::no_newline, element.second ) ); + } + + } + + if( !bid->env_protec.empty() ) { + info.push_back( iteminfo( "DESCRIPTION", _( "Environmental Protection: " ), + iteminfo::no_newline ) ); + for( const auto &element : bid->env_protec ) { + info.push_back( iteminfo( "CBM", body_part_name_as_heading( element.first, 1 ), " ", + iteminfo::no_newline, element.second ) ); + } + + } + + const units::mass weight_bonus = bid->weight_capacity_bonus; + const float weight_modif = bid->weight_capacity_modifier; + if( weight_modif != 1 ) { + std::string modifier; + if( weight_modif < 1 ) { + modifier = "x"; + } else { + modifier = "x"; + } + info.push_back( iteminfo( "CBM", + _( "Weight capacity modifier: " ), modifier, + iteminfo::no_newline | iteminfo::is_decimal, weight_modif ) ); + } + if( weight_bonus != 0_gram ) { + std::string bonus; + if( weight_bonus < 0_gram ) { + bonus = string_format( " %s", weight_units() ); + } else { + bonus = string_format( " %s", weight_units() ); + } + info.push_back( iteminfo( "CBM", _( "Weight capacity bonus: " ), bonus, + iteminfo::no_newline | iteminfo::is_decimal, convert_weight( weight_bonus ) ) ); + } + } if( is_gun() && has_flag( "FIRE_TWOHAND" ) && @@ -4319,6 +4392,24 @@ units::volume item::get_storage() const return storage; } +float item::get_weight_capacity_modifier() const +{ + const islot_armor *t = find_armor_data(); + if( t == nullptr ) { + return 1; + } + return t->weight_capacity_modifier; +} + +units::mass item::get_weight_capacity_bonus() const +{ + const islot_armor *t = find_armor_data(); + if( t == nullptr ) { + return 0_gram; + } + return t->weight_capacity_bonus; +} + int item::get_env_resist( int override_base_resist ) const { const islot_armor *t = find_armor_data(); diff --git a/src/item.h b/src/item.h index a2f6a2b99c36d..e752898dbd47b 100644 --- a/src/item.h +++ b/src/item.h @@ -1469,6 +1469,16 @@ class item : public visitable * character that wears the item. */ units::volume get_storage() const; + /** + * Returns the weight capacity modifier (@ref islot_armor::weight_capacity_modifier) that this item provides when worn. + * For non-armor it returns 1. The modifier is multiplied with the weight capacity of the character that wears the item. + */ + float get_weight_capacity_modifier() const; + /** + * Returns the weight capacity bonus (@ref islot_armor::weight_capacity_modifier) that this item provides when worn. + * For non-armor it returns 0. The bonus is added to the total weight capacity of the character that wears the item. + */ + units::mass get_weight_capacity_bonus() const; /** * Returns the resistance to environmental effects (@ref islot_armor::env_resist) that this * item provides when worn. See @ref player::get_env_resist. Higher values are better. diff --git a/src/item_factory.cpp b/src/item_factory.cpp index 8e5e2bf677c3c..ce59b2e894f2b 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -1509,9 +1509,16 @@ void Item_factory::load( islot_armor &slot, JsonObject &jo, const std::string &s assign( jo, "environmental_protection_with_filter", slot.env_resist_w_filter, strict, 0 ); assign( jo, "warmth", slot.warmth, strict, 0 ); assign( jo, "storage", slot.storage, strict, 0_ml ); + assign( jo, "weight_capacity_modifier", slot.weight_capacity_modifier ); assign( jo, "power_armor", slot.power_armor, strict ); assign_coverage_from_json( jo, "covers", slot.covers, slot.sided ); + + if( jo.has_string( "weight_capacity_bonus" ) ) { + slot.weight_capacity_bonus = read_from_json_string + ( *jo.get_raw( "weight_capacity_bonus" ), units::mass_units ); + } + } void Item_factory::load( islot_pet_armor &slot, JsonObject &jo, const std::string &src ) diff --git a/src/itype.h b/src/itype.h index 20e0e1c1373da..00faf24b00e7b 100644 --- a/src/itype.h +++ b/src/itype.h @@ -247,6 +247,14 @@ struct islot_armor { * How much storage this items provides when worn. */ units::volume storage = 0_ml; + /** + * Factor modifiying weight capacity + */ + float weight_capacity_modifier = 1.0; + /** + * Bonus to weight capacity + */ + units::mass weight_capacity_bonus = 0_gram; /** * Whether this is a power armor item. */ diff --git a/src/units.h b/src/units.h index e54d7ef6c4fde..ffb61c7945f73 100644 --- a/src/units.h +++ b/src/units.h @@ -496,6 +496,11 @@ static const std::vector> energy_units = { { { "kJ", 1_kJ }, } }; +static const std::vector> mass_units = { { + { "g", 1_gram }, + { "kg", 1_kilogram }, + } +}; } // namespace units template