Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add infrastructure for restricting clothing mods #34705

Merged
merged 4 commits into from
Oct 22, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,7 @@ Armor can be defined like this:
"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).
"valid_mods" : ["steel_padded"] // List of valid clothing mods. Note that if the clothing mod doesn't have "restricted" listed, this isn't needed.
```
Alternately, every item (book, tool, gun, even food) can be used as armor if it has armor_data:
```C++
Expand Down Expand Up @@ -2380,6 +2381,7 @@ A flat multiplier on the harvest count of the plant. For numbers greater than on
"item": "leather", // item to consume.
"implement_prompt": "Pad with leather", // prompt to show when implement mod.
"destroy_prompt": "Destroy leather padding", // prompt to show when destroy mod.
"restricted": true, // (optional) If true, clothing must list this mod's flag in "valid_mods" list to use it. Defaults to false.
"mod_value": [ // List of mod effect.
{
"type": "bash", // "bash", "cut", "fire", "acid", "warmth", "storage", and "encumbrance" is available.
Expand Down
1 change: 1 addition & 0 deletions src/clothing_mod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ void clothing_mod::load( JsonObject &jo, const std::string & )
mandatory( jo, was_loaded, "item", item_string );
mandatory( jo, was_loaded, "implement_prompt", implement_prompt );
mandatory( jo, was_loaded, "destroy_prompt", destroy_prompt );
optional( jo, was_loaded, "restricted", restricted, false );

JsonArray jarr = jo.get_array( "mod_value" );
while( jarr.has_more() ) {
Expand Down
1 change: 1 addition & 0 deletions src/clothing_mod.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ struct clothing_mod {
std::string implement_prompt;
std::string destroy_prompt;
std::vector< mod_value > mod_values;
bool restricted;

static size_t count();
};
Expand Down
1 change: 1 addition & 0 deletions src/item_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,7 @@ void Item_factory::load( islot_armor &slot, JsonObject &jo, const std::string &s
assign( jo, "weight_capacity_modifier", slot.weight_capacity_modifier );
assign( jo, "weight_capacity_bonus", slot.weight_capacity_bonus, strict, 0_gram );
assign( jo, "power_armor", slot.power_armor, strict );
assign( jo, "valid_mods", slot.valid_mods, strict );

assign_coverage_from_json( jo, "covers", slot.covers, slot.sided );
}
Expand Down
5 changes: 5 additions & 0 deletions src/itype.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ struct islot_armor {
* Whether this is a power armor item.
*/
bool power_armor = false;
/**
* Whitelisted clothing mods.
* Restricted clothing mods must be listed here by id to be compatible.
*/
std::vector<std::string> valid_mods;
};

struct islot_pet_armor {
Expand Down
51 changes: 35 additions & 16 deletions src/iuse_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4525,11 +4525,8 @@ int sew_advanced_actor::use( player &p, item &it, bool, const tripoint & ) const

// We need extra thread to lose it on bad rolls
const int thread_needed = mod.volume() / 125_ml + 10;
// Returns true if the item already has the mod or if we have enough materials and thread to add it
const auto can_add_mod = [&]( const std::string & new_mod, const itype_id & mat_item ) {
return mod.item_tags.count( new_mod ) > 0 ||
( it.charges >= thread_needed && has_enough[mat_item] );
};

const auto valid_mods = mod.find_armor_data()->valid_mods;

const auto get_compare_color = [&]( const int before, const int after,
const bool higher_is_better ) {
Expand All @@ -4548,25 +4545,47 @@ int sew_advanced_actor::use( player &p, item &it, bool, const tripoint & ) const
};

uilist tmenu;
// TODO: Tell how much thread will we use
if( it.charges >= thread_needed ) {
tmenu.text = _( "How do you want to modify it?" );
} else {
tmenu.text = _( "Not enough thread to modify. Which modification do you want to remove?" );
}
tmenu.text = _( "How do you want to modify it?" );

int index = 0;
for( auto cm : clothing_mods ) {
auto obj = cm.obj();
item temp_item = modded_copy( mod, obj.flag );
temp_item.update_clothing_mod_val();
bool enab = can_add_mod( obj.flag, obj.item_string );

bool enab = false;
std::string prompt;
if( mod.item_tags.count( obj.flag ) == 0 ) {
prompt = string_format( "%s (%d %s)", obj.implement_prompt, items_needed,
item::nname( obj.item_string, items_needed ) );
// Mod not already present, check if modification is possible
if( it.charges < thread_needed ) {
//~ %1$s: modification desc, %2$d: number of thread needed
prompt = string_format( _( "Can't %1$s (need %2$d thread loaded)" ),
obj.implement_prompt, thread_needed );
prompt[6] = std::tolower( prompt[6] );
} else if( !has_enough[obj.item_string] ) {
//~ %1$s: modification desc, %2$d: number of items needed, %3$s: items needed
prompt = string_format( _( "Can't %1$s (need %2$d %3$s)" ), obj.implement_prompt, items_needed,
item::nname( obj.item_string, items_needed ) );
prompt[6] = std::tolower( prompt[6] );
} else if( obj.restricted &&
std::find( valid_mods.begin(), valid_mods.end(), obj.flag ) == valid_mods.end() ) {
//~ %1$s: modification desc, %2$s: mod name
prompt = string_format( _( "Can't %1$s (incompatible with %2$s)" ),
obj.implement_prompt, mod.tname( 1, false ) );
prompt[6] = std::tolower( prompt[6] );
} else {
// Modification is possible
enab = true;
//~ %1$s: modification desc, %2$d: number of items needed, %3$s: items needed, %4$s: number of thread needed
prompt = string_format( _( "%1$s (%2$d %3$s and %4$d thread)" ), obj.implement_prompt, items_needed,
item::nname( obj.item_string, items_needed ), thread_needed );
prompt[0] = std::toupper( prompt[0] );
}

} else {
prompt = obj.destroy_prompt;
// Mod already present, give option to destroy
enab = true;
prompt = _( obj.destroy_prompt );
}
std::ostringstream desc;
desc << format_desc_string( _( "Bash" ), mod.bash_resist(), temp_item.bash_resist(), true );
Expand All @@ -4582,7 +4601,7 @@ int sew_advanced_actor::use( player &p, item &it, bool, const tripoint & ) const
format_volume( before ), volume_units_abbr(), format_volume( after ),
volume_units_abbr() ), get_volume_compare_color( before, after, true ) );

tmenu.addentry_desc( index++, enab, MENU_AUTOASSIGN, _( prompt.c_str() ), desc.str() );
tmenu.addentry_desc( index++, enab, MENU_AUTOASSIGN, prompt.c_str(), desc.str() );
Davi-DeGanne marked this conversation as resolved.
Show resolved Hide resolved
}
tmenu.textwidth = 80;
tmenu.desc_enabled = true;
Expand Down