diff --git a/src/item_factory.cpp b/src/item_factory.cpp index 767250d3ab7fe..4db394cfcbb87 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -2479,24 +2479,37 @@ static void apply_optional( T &value, const cata::optional &applied ) } } +// Gets around the issue that cata::optional doesn't support +// the *= and += operators required for "proportional" and "relative". +template +static void get_optional( const JsonObject &jo, bool was_loaded, const std::string &member, + cata::optional &value ) +{ + T tmp; + if( value ) { + tmp = *value; + } + optional( jo, was_loaded, member, tmp ); + if( jo.has_member( member ) ) { + value = tmp; + } +} + void islot_armor::load( const JsonObject &jo ) { optional( jo, was_loaded, "armor", sub_data ); - cata::optional thickness; - cata::optional env_resist; - cata::optional env_resist_w_filter; cata::optional covers; assign_coverage_from_json( jo, "covers", covers ); - optional( jo, false, "material_thickness", thickness, cata::nullopt ); - optional( jo, false, "environmental_protection", env_resist, cata::nullopt ); - optional( jo, false, "environmental_protection_with_filter", env_resist_w_filter, cata::nullopt ); + get_optional( jo, was_loaded, "material_thickness", _material_thickness ); + get_optional( jo, was_loaded, "environmental_protection", _env_resist ); + get_optional( jo, was_loaded, "environmental_protection_with_filter", _env_resist_w_filter ); for( armor_portion_data &armor : sub_data ) { - apply_optional( armor.avg_thickness, thickness ); - apply_optional( armor.env_resist, env_resist ); - apply_optional( armor.env_resist_w_filter, env_resist_w_filter ); + apply_optional( armor.avg_thickness, _material_thickness ); + apply_optional( armor.env_resist, _env_resist ); + apply_optional( armor.env_resist_w_filter, _env_resist_w_filter ); if( covers ) { armor.covers = covers; } diff --git a/src/itype.h b/src/itype.h index 235f73d3ad051..ebb0a730b7d05 100644 --- a/src/itype.h +++ b/src/itype.h @@ -309,77 +309,84 @@ struct armor_portion_data { }; struct islot_armor { - /** - * Whether this item can be worn on either side of the body - */ - bool sided = false; - /** - * The Non-Functional variant of this item. Currently only applies to ablative plates - */ - itype_id non_functional; - /** - * How much warmth this item provides. - */ - int warmth = 0; - /** - * Factor modifying weight capacity - */ - float weight_capacity_modifier = 1.0f; - /** - * Bonus to weight capacity - */ - units::mass weight_capacity_bonus = 0_gram; - /** - * Whether this is a power armor item. - */ - bool power_armor = false; - /** - * Whether this item has ablative pockets - */ - bool ablative = false; - /** - * Whether this item has pockets that generate additional encumbrance - */ - bool additional_pocket_enc = false; - /** - * Whether this item has pockets that can be ripped off - */ - bool ripoff_chance = false; - /** - * Whether this item has pockets that are noisy - */ - bool noisy = false; - /** - * Whitelisted clothing mods. - * Restricted clothing mods must be listed here by id to be compatible. - */ - std::vector valid_mods; + public: + /** + * Whether this item can be worn on either side of the body + */ + bool sided = false; + /** + * The Non-Functional variant of this item. Currently only applies to ablative plates + */ + itype_id non_functional; + /** + * How much warmth this item provides. + */ + int warmth = 0; + /** + * Factor modifying weight capacity + */ + float weight_capacity_modifier = 1.0f; + /** + * Bonus to weight capacity + */ + units::mass weight_capacity_bonus = 0_gram; + /** + * Whether this is a power armor item. + */ + bool power_armor = false; + /** + * Whether this item has ablative pockets + */ + bool ablative = false; + /** + * Whether this item has pockets that generate additional encumbrance + */ + bool additional_pocket_enc = false; + /** + * Whether this item has pockets that can be ripped off + */ + bool ripoff_chance = false; + /** + * Whether this item has pockets that are noisy + */ + bool noisy = false; + /** + * Whitelisted clothing mods. + * Restricted clothing mods must be listed here by id to be compatible. + */ + std::vector valid_mods; - /** - * If the item in question has any sub coverage when testing for encumberance - */ - bool has_sub_coverage = false; + /** + * If the item in question has any sub coverage when testing for encumberance + */ + bool has_sub_coverage = false; - // Layer, encumbrance and coverage information for each body part. - // This isn't directly loaded in but is instead generated from the loaded in - // sub_data vector - std::vector data; + // Layer, encumbrance and coverage information for each body part. + // This isn't directly loaded in but is instead generated from the loaded in + // sub_data vector + std::vector data; - // Layer, encumbrance and coverage information for each sub body part. - // This vector can have duplicates for body parts themselves. - std::vector sub_data; + // Layer, encumbrance and coverage information for each sub body part. + // This vector can have duplicates for body parts themselves. + std::vector sub_data; - // all of the layers this item is involved in - std::vector all_layers; + // all of the layers this item is involved in + std::vector all_layers; - bool was_loaded = false; + bool was_loaded = false; - int avg_env_resist() const; - int avg_env_resist_w_filter() const; - float avg_thickness() const; + int avg_env_resist() const; + int avg_env_resist_w_filter() const; + float avg_thickness() const; - void load( const JsonObject &jo ); - void deserialize( const JsonObject &jo ); + void load( const JsonObject &jo ); + void deserialize( const JsonObject &jo ); + + private: + // Base material thickness, used to derive thickness in sub_data + cata::optional _material_thickness = 0.0f; + cata::optional _env_resist = 0; + cata::optional _env_resist_w_filter = 0; }; struct islot_pet_armor {