From 9e175fd702d3e909becdbf5f40d3700bdc885828 Mon Sep 17 00:00:00 2001 From: Ishta Tann Date: Fri, 13 Dec 2019 17:03:57 -0800 Subject: [PATCH 1/9] Reworked how crafting skill requirement display is generated. --- src/basecamp.cpp | 2 +- src/crafting_gui.cpp | 15 ++------- src/recipe.cpp | 71 +++++++++++++++++++-------------------- src/recipe.h | 62 ++++++++++++++++++++++++++++++++-- src/recipe_dictionary.cpp | 3 +- 5 files changed, 98 insertions(+), 55 deletions(-) diff --git a/src/basecamp.cpp b/src/basecamp.cpp index 1cddbd75f418b..2f461833b11bb 100644 --- a/src/basecamp.cpp +++ b/src/basecamp.cpp @@ -219,7 +219,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 d3b055b0704b9..0a9c3f267f067 100644 --- a/src/crafting_gui.cpp +++ b/src/crafting_gui.cpp @@ -565,23 +565,14 @@ const recipe *select_crafting_recipe( int &batch_size ) if( display_mode == 0 ) { const int width = getmaxx( w_data ) - xpos - item_info_x; - 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 ), width, 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 e0ac262b4ddc3..f81d3b40f8ac0 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -418,52 +418,49 @@ bool recipe::has_byproducts() const return !byproducts.empty(); } -std::string recipe::required_skills_string( const Character *c, bool print_skill_level ) const +std::string recipe::primary_skill_string( const Character *c, bool print_skill_level ) const { - 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 ); - } + std::list< std::pair > skillList; + + if( skill_used != skill_id( "none" ) ) { + skillList.push_back( std::pair( skill_used, difficulty ) ); } - return enumerate_as_string( required_skills.begin(), required_skills.end(), - [&]( 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"; - std::string skill_level_string = print_skill_level ? "" : ( std::to_string( player_skill ) + "/" ); - skill_level_string += std::to_string( skill.second ); - return string_format( "%s (%s)", - skill.first.obj().name(), difficulty_color, skill_level_string ); - } ); + + return required_skills_string( skillList.begin(), skillList.end(), c, print_skill_level ); } -std::string recipe::required_skills_string( const Character *c ) const +std::string recipe::required_skills_string( const Character *c, bool include_primary_skill, + bool print_skill_level ) const { - return required_skills_string( c, false ); + // There is no primary skill used or it shouldn't be included then we can just use the required_skills directly. + if( skill_used == skill_id( "none" ) || !include_primary_skill ) { + return required_skills_string( required_skills.begin(), required_skills.end(), c, + print_skill_level ); + } + + std::list< std::pair > skillList; + skillList.push_back( std::pair( skill_used, difficulty ) ); + for( const std::pair &skill : required_skills ) { + skillList.push_back( skill ); + } + + return required_skills_string( skillList.begin(), skillList.end(), c, print_skill_level ); } -std::string recipe::required_skills_string() const +std::string recipe::required_all_skills_string() const { - if( required_skills.empty() ) { - if( difficulty == 0 ) { - return _( "none" ); - } else { - return string_format( "%s: %d", skill_used.obj().name(), - difficulty ); - } + // There is no primary skill used, we can just use the required_skills directly. + if( skill_used == skill_id( "none" ) ) { + return required_skills_string( required_skills.begin(), required_skills.end() ); } - return enumerate_as_string( required_skills.begin(), required_skills.end(), - [&]( const std::pair &skill ) { - return string_format( "%s: %d", skill.first.obj().name(), - skill.second ); - } ); + + std::list< std::pair > skillList; + skillList.push_back( std::pair( skill_used, difficulty ) ); + for( const std::pair &skill : required_skills ) { + skillList.push_back( skill ); + } + + return required_skills_string( skillList.begin(), skillList.end() ); } std::string recipe::batch_savings_string() const diff --git a/src/recipe.h b/src/recipe.h index 89374a519f572..0c99408bfed32 100644 --- a/src/recipe.h +++ b/src/recipe.h @@ -104,9 +104,31 @@ 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; + + // 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_string( _FIter first, _FIter last, const Character *c, + const bool print_skill_level ) const; + + // Format a std::pair for the basecamp bulletin board. + // skill colored white with difficulty in parenthesis. + template + std::string required_skills_string( _FIter first, _FIter last ) const; + // Create a string to describe the time savings of batch-crafting, if any. // Format: "N% at >M units" or "none" @@ -202,4 +224,38 @@ class recipe bool bp_autocalc = false; }; +template +std::string recipe::required_skills_string( _FIter first, _FIter last, const Character *c, + const bool print_skill_level ) const +{ + if( first == last ) { + return _( "none" ); + } + + 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"; + std::string skill_level_string = print_skill_level ? "" : ( std::to_string( player_skill ) + "/" ); + skill_level_string += std::to_string( skill.second ); + return string_format( "%s (%s)", + skill.first.obj().name(), difficulty_color, skill_level_string ); + } ); +} + +template +std::string recipe::required_skills_string( _FIter first, _FIter last ) +const +{ + if( first == last ) { + return _( "none" ); + } + + return enumerate_as_string( first, last, + [&]( const std::pair &skill ) { + return string_format( "%s (%d)", skill.first.obj().name(), + skill.second ); + } ); +} + #endif // RECIPE_H diff --git a/src/recipe_dictionary.cpp b/src/recipe_dictionary.cpp index 68efd587926c7..2a71fc2ef731d 100644 --- a/src/recipe_dictionary.cpp +++ b/src/recipe_dictionary.cpp @@ -157,8 +157,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 ); From e22456018b4c3e9c0ec3e096ef8cde39900c49fe Mon Sep 17 00:00:00 2001 From: Ishta Tann Date: Fri, 13 Dec 2019 17:23:29 -0800 Subject: [PATCH 2/9] Include skill.h so that the templates have complete types. --- src/recipe.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/recipe.h b/src/recipe.h index 0c99408bfed32..ff83a64570a15 100644 --- a/src/recipe.h +++ b/src/recipe.h @@ -11,6 +11,7 @@ #include #include "requirements.h" +#include "skill.h" #include "translations.h" #include "type_id.h" From 93c1c67e5e7f4b8d2effc0b88baed520ee9bd6cb Mon Sep 17 00:00:00 2001 From: Ishta Tann Date: Fri, 13 Dec 2019 18:02:48 -0800 Subject: [PATCH 3/9] Include character.h so that the templates have complete types. --- src/recipe.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/recipe.h b/src/recipe.h index ff83a64570a15..4ac5542c5425d 100644 --- a/src/recipe.h +++ b/src/recipe.h @@ -10,6 +10,7 @@ #include #include +#include "character.h" #include "requirements.h" #include "skill.h" #include "translations.h" From 79db7a9fe17ba0872de5902a53ecbcc0e797f885 Mon Sep 17 00:00:00 2001 From: ishtatann <58312745+ishtatann@users.noreply.github.com> Date: Sat, 14 Dec 2019 18:52:57 -0800 Subject: [PATCH 4/9] use is_null instead of comparing against "none". Co-Authored-By: BevapDin --- src/recipe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipe.cpp b/src/recipe.cpp index f81d3b40f8ac0..17038a98096f8 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -422,7 +422,7 @@ std::string recipe::primary_skill_string( const Character *c, bool print_skill_l { std::list< std::pair > skillList; - if( skill_used != skill_id( "none" ) ) { + if( !skill_used.is_null() ) { skillList.push_back( std::pair( skill_used, difficulty ) ); } From d88389c375ae92c9bdf65ae17eed0f77047d84e1 Mon Sep 17 00:00:00 2001 From: ishtatann <58312745+ishtatann@users.noreply.github.com> Date: Sat, 14 Dec 2019 18:53:14 -0800 Subject: [PATCH 5/9] use is_null instead of comparing against "none". Co-Authored-By: BevapDin --- src/recipe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipe.cpp b/src/recipe.cpp index 17038a98096f8..a4112034b92d6 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -433,7 +433,7 @@ std::string recipe::required_skills_string( const Character *c, bool include_pri 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 == skill_id( "none" ) || !include_primary_skill ) { + if( skill_used.is_null() || !include_primary_skill ) { return required_skills_string( required_skills.begin(), required_skills.end(), c, print_skill_level ); } From b39a3906ae31652c7a32721828785a2754b19e7d Mon Sep 17 00:00:00 2001 From: ishtatann <58312745+ishtatann@users.noreply.github.com> Date: Sat, 14 Dec 2019 18:54:12 -0800 Subject: [PATCH 6/9] use is_null instead of comparing against "none". Co-Authored-By: BevapDin --- src/recipe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipe.cpp b/src/recipe.cpp index a4112034b92d6..a9239bda106bb 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -450,7 +450,7 @@ std::string recipe::required_skills_string( const Character *c, bool include_pri 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 == skill_id( "none" ) ) { + if( skill_used.is_null() ) { return required_skills_string( required_skills.begin(), required_skills.end() ); } From d2506191ac80ed345d7c152935ef5a65567b6109 Mon Sep 17 00:00:00 2001 From: Ishta Tann Date: Sat, 14 Dec 2019 19:15:54 -0800 Subject: [PATCH 7/9] Moved the templates from recipe.h to recipe.cpp. Removed the includes I had added into recipe.h for the templates. Moved the templates out of the recipe class since the templates didn't access any member variables. Renamed the templates from required_skills_string to required_skills_as_string to avoid confusing the compiler. --- src/recipe.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++------ src/recipe.h | 48 ------------------------------------------------ 2 files changed, 44 insertions(+), 54 deletions(-) diff --git a/src/recipe.cpp b/src/recipe.cpp index a9239bda106bb..28c8001dae54e 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -418,6 +418,44 @@ bool recipe::has_byproducts() const return !byproducts.empty(); } +// 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( _FIter first, _FIter last, const Character *c, + const bool print_skill_level ) +{ + if( first == last ) { + return _( "none" ); + } + + 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"; + std::string skill_level_string = print_skill_level ? "" : ( std::to_string( player_skill ) + "/" ); + skill_level_string += std::to_string( skill.second ); + return string_format( "%s (%s)", + skill.first.obj().name(), difficulty_color, skill_level_string ); + } ); +} + +// Format a std::pair for the basecamp bulletin board. +// skill colored white with difficulty in parenthesis. +template +std::string required_skills_as_string( _FIter first, _FIter last ) +{ + if( first == last ) { + return _( "none" ); + } + + return enumerate_as_string( first, last, + [&]( const std::pair &skill ) { + 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::list< std::pair > skillList; @@ -426,7 +464,7 @@ std::string recipe::primary_skill_string( const Character *c, bool print_skill_l skillList.push_back( std::pair( skill_used, difficulty ) ); } - return required_skills_string( skillList.begin(), skillList.end(), c, print_skill_level ); + 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, @@ -434,8 +472,8 @@ std::string recipe::required_skills_string( const Character *c, bool include_pri { // 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_string( required_skills.begin(), required_skills.end(), c, - print_skill_level ); + return required_skills_as_string( required_skills.begin(), required_skills.end(), c, + print_skill_level ); } std::list< std::pair > skillList; @@ -444,14 +482,14 @@ std::string recipe::required_skills_string( const Character *c, bool include_pri skillList.push_back( skill ); } - return required_skills_string( skillList.begin(), skillList.end(), c, print_skill_level ); + 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_string( required_skills.begin(), required_skills.end() ); + return required_skills_as_string( required_skills.begin(), required_skills.end() ); } std::list< std::pair > skillList; @@ -460,7 +498,7 @@ std::string recipe::required_all_skills_string() const skillList.push_back( skill ); } - return required_skills_string( skillList.begin(), skillList.end() ); + return required_skills_as_string( skillList.begin(), skillList.end() ); } std::string recipe::batch_savings_string() const diff --git a/src/recipe.h b/src/recipe.h index 4ac5542c5425d..505095359eac1 100644 --- a/src/recipe.h +++ b/src/recipe.h @@ -10,9 +10,7 @@ #include #include -#include "character.h" #include "requirements.h" -#include "skill.h" #include "translations.h" #include "type_id.h" @@ -119,18 +117,6 @@ class recipe // This is used by the basecamp bulletin board. std::string required_all_skills_string() 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_string( _FIter first, _FIter last, const Character *c, - const bool print_skill_level ) const; - - // Format a std::pair for the basecamp bulletin board. - // skill colored white with difficulty in parenthesis. - template - std::string required_skills_string( _FIter first, _FIter last ) const; - // Create a string to describe the time savings of batch-crafting, if any. // Format: "N% at >M units" or "none" @@ -226,38 +212,4 @@ class recipe bool bp_autocalc = false; }; -template -std::string recipe::required_skills_string( _FIter first, _FIter last, const Character *c, - const bool print_skill_level ) const -{ - if( first == last ) { - return _( "none" ); - } - - 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"; - std::string skill_level_string = print_skill_level ? "" : ( std::to_string( player_skill ) + "/" ); - skill_level_string += std::to_string( skill.second ); - return string_format( "%s (%s)", - skill.first.obj().name(), difficulty_color, skill_level_string ); - } ); -} - -template -std::string recipe::required_skills_string( _FIter first, _FIter last ) -const -{ - if( first == last ) { - return _( "none" ); - } - - return enumerate_as_string( first, last, - [&]( const std::pair &skill ) { - return string_format( "%s (%d)", skill.first.obj().name(), - skill.second ); - } ); -} - #endif // RECIPE_H From e9cbab08f37d591ae3cfbe03867cbbf8a9e26c25 Mon Sep 17 00:00:00 2001 From: ishtatann <58312745+ishtatann@users.noreply.github.com> Date: Mon, 16 Dec 2019 19:09:00 -0800 Subject: [PATCH 8/9] Switch from list to vector. Co-Authored-By: John Bytheway --- src/recipe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipe.cpp b/src/recipe.cpp index 28c8001dae54e..047882f221486 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -458,7 +458,7 @@ std::string required_skills_as_string( _FIter first, _FIter last ) std::string recipe::primary_skill_string( const Character *c, bool print_skill_level ) const { - std::list< std::pair > skillList; + std::vector< std::pair > skillList; if( !skill_used.is_null() ) { skillList.push_back( std::pair( skill_used, difficulty ) ); From 157857f5662b74d81e58b5db1d6a742828fee04d Mon Sep 17 00:00:00 2001 From: Ishta Tann Date: Mon, 16 Dec 2019 19:24:42 -0800 Subject: [PATCH 9/9] Switch from list to vector. Fix naming convention on the template iterators. Use copy instead of for loop. Addressing PR comments. --- src/recipe.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/recipe.cpp b/src/recipe.cpp index 047882f221486..9477a4c503cdd 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -421,8 +421,8 @@ bool recipe::has_byproducts() 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( _FIter first, _FIter last, const Character *c, +template +std::string required_skills_as_string( Iter first, Iter last, const Character *c, const bool print_skill_level ) { if( first == last ) { @@ -442,8 +442,8 @@ std::string required_skills_as_string( _FIter first, _FIter last, const Characte // Format a std::pair for the basecamp bulletin board. // skill colored white with difficulty in parenthesis. -template -std::string required_skills_as_string( _FIter first, _FIter last ) +template +std::string required_skills_as_string( Iter first, Iter last ) { if( first == last ) { return _( "none" ); @@ -476,11 +476,10 @@ std::string recipe::required_skills_string( const Character *c, bool include_pri print_skill_level ); } - std::list< std::pair > skillList; + std::vector< std::pair > skillList; skillList.push_back( std::pair( skill_used, difficulty ) ); - for( const std::pair &skill : required_skills ) { - skillList.push_back( skill ); - } + 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 ); } @@ -492,11 +491,10 @@ std::string recipe::required_all_skills_string() const return required_skills_as_string( required_skills.begin(), required_skills.end() ); } - std::list< std::pair > skillList; + std::vector< std::pair > skillList; skillList.push_back( std::pair( skill_used, difficulty ) ); - for( const std::pair &skill : required_skills ) { - skillList.push_back( skill ); - } + std::copy( required_skills.begin(), required_skills.end(), + std::back_inserter > >( skillList ) ); return required_skills_as_string( skillList.begin(), skillList.end() ); }