Skip to content

Commit

Permalink
Proportional Material (CleverRaven#52369)
Browse files Browse the repository at this point in the history
* Read "material" as string tags or portioned objects
* Proportional damage resistance per material
* Use the highest "portion" material as the base
* Track insertion order for std::map
* Fix materials being accessed before loading mods
* Additional proportional effects for materials
Take the proportion of certain materials into account for:
- Glass breaking (from smashing, striking, throwing, etc.)
- Weapons can have up to 20% glass before not being able to counter
- Magnetic pull is less effective for items with lower metal content
  • Loading branch information
dseguin authored Oct 23, 2021
1 parent eac7d3f commit fcab0db
Show file tree
Hide file tree
Showing 22 changed files with 308 additions and 172 deletions.
17 changes: 13 additions & 4 deletions doc/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2376,7 +2376,10 @@ See also VEHICLE_JSON.md
"insulation": 1, // (Optional, default = 1) If container or vehicle part, how much insulation should it provide to the contents
"price": 100, // Used when bartering with NPCs. For stackable items (ammo, comestibles) this is the price for stack_size charges. Can use string "cent" "USD" or "kUSD".
"price_postapoc": "1 USD", // Same as price but represent value post cataclysm. Can use string "cent" "USD" or "kUSD".
"material": ["COTTON"], // Material types, can be as many as you want. See materials.json for possible options
"material": [ // Material types, can be as many as you want. See materials.json for possible options
{ "type": "cotton", "portion": 9 }, // type indicates the material's ID, portion indicates proportionally how much of the item is composed of that material
{ "type": "plastic" } // portion can be omitted and will default to 1. In this case, the item is 90% cotton and 10% plastic.
],
"weapon_category": [ "WEAPON_CAT1" ], // (Optional) Weapon categories this item is in for martial arts.
"cutting": 0, // (Optional, default = 0) Cutting damage caused by using it as a melee weapon. This value cannot be negative.
"bashing": 0, // (Optional, default = 0) Bashing damage caused by using it as a melee weapon. This value cannot be negative.
Expand Down Expand Up @@ -2768,7 +2771,10 @@ CBMs can be defined like this:
"parasites": 10, // (Optional) Probability of becoming parasitised when eating
"contamination": [ { "disease": "bad_food", "probability": 5 } ], // (Optional) List of diseases carried by this comestible and their associated probability. Values must be in the [0, 100] range.
"vitamins": [ [ "calcium", 5 ], [ "iron", 12 ] ], // Vitamins provided by consuming a charge (portion) of this. An integer percentage of ideal daily value average. Vitamins array keys include the following: calcium, iron, vitA, vitB, vitC, mutant_toxin, bad_food, blood, and redcells. Note that vitB is B12.
"material": [ "flesh", "wheat" ], // All materials (IDs) this food is made of
"material": [ // All materials (IDs) this food is made of
{ "type": "flesh", "portion": 3 }, // See Generic Item attributes for type and portion details
{ "type": "wheat", "portion": 5 }
],
"primary_material": "meat", // What the primary material ID is. Materials determine specific heat.
"rot_spawn": "MONSTERGROUP_NAME", // Monster group that spawns when food becomes rotten (used for egg hatching)
"rot_spawn_chance": 10, // Percent chance of monstergroup spawn when food rots. Max 100.
Expand Down Expand Up @@ -2819,7 +2825,10 @@ Any Item can be a container. To add the ability to contain things to an item, yo
"name": "hatchet", // In-game name displayed
"description": "A one-handed hatchet. Makes a great melee weapon, and is useful both for cutting wood, and for use as a hammer.", // In-game description
"price": 95, // Used when bartering with NPCs. Can use string "cent" "USD" or "kUSD".
"material": ["iron", "wood"], // Material types. See materials.json for possible options
"material": [ // Material types. See materials.json for possible options
{ "type": "iron", "portion": 2 }, // See Generic Item attributes for type and portion details
{ "type": "wood", "portion": 3 }
],
"weight": 907, // Weight, measured in grams
"volume": "1500 ml", // Volume, volume in ml and L can be used - "50 ml" or "2 L"
"bashing": 12, // Bashing damage caused by using it as a melee weapon
Expand Down Expand Up @@ -2933,7 +2942,7 @@ Alternately, every item (book, tool, armor, even food) can be used as a gunmod i
"name": "torch (lit)", // In-game name displayed
"description": "A large stick, wrapped in gasoline soaked rags. This is burning, producing plenty of light", // In-game description
"price": 0, // Used when bartering with NPCs. Can use string "cent" "USD" or "kUSD".
"material": [ "wood" ], // Material types. See materials.json for possible options
"material": [ { "type": "wood", "portion": 1 } ], // Material types. See materials.json for possible options. Also see Generic Item attributes for type and portion details
"techniques": [ "FLAMING" ], // Combat techniques used by this tool
"flags": [ "FIRE" ], // Indicates special effects
"weight": 831, // Weight, measured in grams
Expand Down
14 changes: 8 additions & 6 deletions src/auto_pickup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

using namespace auto_pickup;

static bool check_special_rule( const std::vector<material_id> &materials,
static bool check_special_rule( const std::map<material_id, int> &materials,
const std::string &rule );

auto_pickup::player_settings &get_auto_pickup()
Expand Down Expand Up @@ -610,7 +610,7 @@ bool player_settings::empty() const
return global_rules.empty() && character_rules.empty();
}

bool check_special_rule( const std::vector<material_id> &materials, const std::string &rule )
bool check_special_rule( const std::map<material_id, int> &materials, const std::string &rule )
{
char type = ' ';
std::vector<std::string> filter;
Expand All @@ -624,16 +624,18 @@ bool check_special_rule( const std::vector<material_id> &materials, const std::s
}

if( type == 'm' ) {
return std::any_of( materials.begin(), materials.end(), [&filter]( const material_id & mat ) {
return std::any_of( materials.begin(),
materials.end(), [&filter]( const std::pair<material_id, int> &mat ) {
return std::any_of( filter.begin(), filter.end(), [&mat]( const std::string & search ) {
return lcmatch( mat->name(), search );
return lcmatch( mat.first->name(), search );
} );
} );

} else if( type == 'M' ) {
return std::all_of( materials.begin(), materials.end(), [&filter]( const material_id & mat ) {
return std::all_of( materials.begin(),
materials.end(), [&filter]( const std::pair<material_id, int> &mat ) {
return std::any_of( filter.begin(), filter.end(), [&mat]( const std::string & search ) {
return lcmatch( mat->name(), search );
return lcmatch( mat.first->name(), search );
} );
} );
}
Expand Down
2 changes: 1 addition & 1 deletion src/consumption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ ret_val<edible_rating> Character::can_eat( const item &food ) const

if( edible || drinkable ) {
for( const auto &elem : food.type->materials ) {
if( !elem->edible() ) {
if( !elem.first->edible() ) {
return ret_val<edible_rating>::make_failure( _( "That doesn't look edible in its current form." ) );
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4749,7 +4749,9 @@ bool game::forced_door_closing( const tripoint &p, const ter_id &door_type, int
it = items.erase( it );
continue;
}
if( it->made_of( material_id( "glass" ) ) && one_in( 2 ) ) {
const int glass_portion = it->made_of( material_id( "glass" ) );
const float glass_fraction = glass_portion / static_cast<float>( it->type->mat_portion_total );
if( glass_portion && rng_float( 0.0f, 1.0f ) < glass_fraction * 0.5f ) {
if( can_see ) {
add_msg( m_warning, _( "A %s shatters!" ), it->tname() );
} else {
Expand Down
10 changes: 7 additions & 3 deletions src/handle_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -809,9 +809,13 @@ static void smash()
if( player_character.get_skill_level( skill_melee ) == 0 ) {
player_character.practice( skill_melee, rng( 0, 1 ) * rng( 0, 1 ) );
}
const int vol = weapon.volume() / units::legacy_volume_factor;
if( weapon.made_of( material_id( "glass" ) ) &&
rng( 0, vol + 3 ) < vol ) {
const int glass_portion = weapon.made_of( material_id( "glass" ) );
float glass_fraction = glass_portion / static_cast<float>( weapon.type->mat_portion_total );
if( std::isnan( glass_fraction ) || glass_fraction > 1.f ) {
glass_fraction = 0.f;
}
const int vol = weapon.volume() * glass_fraction / units::legacy_volume_factor;
if( glass_portion && rng( 0, vol + 3 ) < vol ) {
add_msg( m_bad, _( "Your %s shatters!" ), weapon.tname() );
weapon.spill_contents( player_character.pos() );
sounds::sound( player_character.pos(), 24, sounds::sound_t::combat, "CRACK!", true, "smash",
Expand Down
Loading

0 comments on commit fcab0db

Please sign in to comment.