diff --git a/src/basecamp.cpp b/src/basecamp.cpp index 3c7a49f67c428..8573b5ca59657 100644 --- a/src/basecamp.cpp +++ b/src/basecamp.cpp @@ -221,7 +221,7 @@ std::string basecamp::om_upgrade_description( const std::string &bldg, bool trun comp = comp + elem + "\n"; } comp = string_format( _( "Notes:\n%s\n\nSkills used: %s\n%s\n" ), - making.description, making.required_skills_string(), comp ); + making.description, making.required_all_skills_string(), comp ); if( !trunc ) { time_duration base_time = making.batch_duration(); comp += string_format( _( "Risk: None\nTime: %s\n" ), diff --git a/src/crafting_gui.cpp b/src/crafting_gui.cpp index 8d286387e31d2..c187a378ee9e4 100644 --- a/src/crafting_gui.cpp +++ b/src/crafting_gui.cpp @@ -488,23 +488,14 @@ const recipe *select_crafting_recipe( int &batch_size ) const int xpos = 30; if( display_mode == 0 ) { - auto player_skill = g->u.get_skill_level( current[line]->skill_used ); - std::string difficulty_color = - current[line]->difficulty > player_skill ? "yellow" : "green"; - std::string primary_skill_level = string_format( "(%s/%s)", player_skill, - current[line]->difficulty ); print_colored_text( w_data, point( xpos, ypos++ ), col, col, - string_format( _( "Primary skill: %s %s" ), - ( !current[line]->skill_used ? _( "N/A" ) : - current[line]->skill_used.obj().name() ), - difficulty_color, - ( !current[line]->skill_used ? "" : primary_skill_level ) - ) ); + string_format( _( "Primary skill: %s" ), + current[line]->primary_skill_string( &g->u, false ) ) ); ypos += fold_and_print( w_data, point( xpos, ypos ), pane, col, _( "Other skills: %s" ), - current[line]->required_skills_string( &g->u ) ); + current[line]->required_skills_string( &g->u, false, false ) ); const int expected_turns = g->u.expected_time_to_craft( *current[line], count ) / to_moves( 1_turns ); diff --git a/src/recipe.cpp b/src/recipe.cpp index 323eefee09d77..0381b5d68d6f0 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -471,22 +471,18 @@ bool recipe::has_byproducts() const return !byproducts.empty(); } -std::string recipe::required_skills_string( const Character *c, bool print_skill_level ) const +// Format a std::pair for the crafting menu. +// skill colored green (or yellow if beyond characters skill) +// optionally with the skill level (player / difficulty) +template +std::string required_skills_as_string( Iter first, Iter last, const Character *c, + const bool print_skill_level ) { - if( required_skills.empty() ) { - if( difficulty == 0 ) { - return _( "none" ); - } else { - const int player_skill = c ? c->get_skill_level( skill_used ) : 0; - std::string difficulty_color = difficulty > player_skill ? "yellow" : "green"; - std::string skill_level_string = print_skill_level ? "" : - ( std::to_string( player_skill ) + "/" ); - skill_level_string += std::to_string( difficulty ); - return string_format( "%s (%s)", - skill_used.obj().name(), difficulty_color, skill_level_string ); - } + if( first == last ) { + return _( "none" ); } - return enumerate_as_string( required_skills.begin(), required_skills.end(), + + return enumerate_as_string( first, last, [&]( const std::pair &skill ) { const int player_skill = c ? c->get_skill_level( skill.first ) : 0; std::string difficulty_color = skill.second > player_skill ? "yellow" : "green"; @@ -497,28 +493,65 @@ std::string recipe::required_skills_string( const Character *c, bool print_skill } ); } -std::string recipe::required_skills_string( const Character *c ) const +// Format a std::pair for the basecamp bulletin board. +// skill colored white with difficulty in parenthesis. +template +std::string required_skills_as_string( Iter first, Iter last ) { - return required_skills_string( c, false ); -} - -std::string recipe::required_skills_string() const -{ - if( required_skills.empty() ) { - if( difficulty == 0 ) { - return _( "none" ); - } else { - return string_format( "%s: %d", skill_used.obj().name(), - difficulty ); - } + if( first == last ) { + return _( "none" ); } - return enumerate_as_string( required_skills.begin(), required_skills.end(), + + return enumerate_as_string( first, last, [&]( const std::pair &skill ) { - return string_format( "%s: %d", skill.first.obj().name(), + return string_format( "%s (%d)", skill.first.obj().name(), skill.second ); } ); } +std::string recipe::primary_skill_string( const Character *c, bool print_skill_level ) const +{ + std::vector< std::pair > skillList; + + if( !skill_used.is_null() ) { + skillList.push_back( std::pair( skill_used, difficulty ) ); + } + + return required_skills_as_string( skillList.begin(), skillList.end(), c, print_skill_level ); +} + +std::string recipe::required_skills_string( const Character *c, bool include_primary_skill, + bool print_skill_level ) const +{ + // There is no primary skill used or it shouldn't be included then we can just use the required_skills directly. + if( skill_used.is_null() || !include_primary_skill ) { + return required_skills_as_string( required_skills.begin(), required_skills.end(), c, + print_skill_level ); + } + + std::vector< std::pair > skillList; + skillList.push_back( std::pair( skill_used, difficulty ) ); + std::copy( required_skills.begin(), required_skills.end(), + std::back_inserter > >( skillList ) ); + + return required_skills_as_string( skillList.begin(), skillList.end(), c, print_skill_level ); +} + +std::string recipe::required_all_skills_string() const +{ + // There is no primary skill used, we can just use the required_skills directly. + if( skill_used.is_null() ) { + return required_skills_as_string( required_skills.begin(), required_skills.end() ); + } + + std::vector< std::pair > skillList; + skillList.push_back( std::pair( skill_used, difficulty ) ); + std::copy( required_skills.begin(), required_skills.end(), + std::back_inserter > >( skillList ) ); + + return required_skills_as_string( skillList.begin(), skillList.end() ); +} + std::string recipe::batch_savings_string() const { return ( batch_rsize != 0 ) ? diff --git a/src/recipe.h b/src/recipe.h index cf7fdac5ade91..58a219420a475 100644 --- a/src/recipe.h +++ b/src/recipe.h @@ -117,9 +117,19 @@ class recipe // Create a string list to describe the skill requirements for this recipe // Format: skill_name(level/amount), skill_name(level/amount) // Character object (if provided) used to color levels - std::string required_skills_string( const Character *, bool print_skill_level ) const; - std::string required_skills_string( const Character * ) const; - std::string required_skills_string() const; + + // These are primarily used by the crafting menu. + // Format the primary skill string. + std::string primary_skill_string( const Character *c, bool print_skill_level ) const; + + // Format the other skills string. This is also used for searching within the crafting + // menu which includes the primary skill. + std::string required_skills_string( const Character *, bool include_primary_skill, + bool print_skill_level ) const; + + // This is used by the basecamp bulletin board. + std::string required_all_skills_string() const; + // Create a string to describe the time savings of batch-crafting, if any. // Format: "N% at >M units" or "none" diff --git a/src/recipe_dictionary.cpp b/src/recipe_dictionary.cpp index 3c90a2a34bc83..0c861241f5558 100644 --- a/src/recipe_dictionary.cpp +++ b/src/recipe_dictionary.cpp @@ -158,8 +158,7 @@ std::vector recipe_subset::search( const std::string &txt, return lcmatch( r->result_name(), txt ); case search_type::skill: - return lcmatch( r->required_skills_string( nullptr ), txt ) || - lcmatch( r->skill_used->name(), txt ); + return lcmatch( r->required_skills_string( nullptr, true, false ), txt ); case search_type::primary_skill: return lcmatch( r->skill_used->name(), txt );