Skip to content

Commit

Permalink
Compare recipe result with inventory item (CleverRaven#68139)
Browse files Browse the repository at this point in the history
* Adds ability to press `I` when in `&` crafting screen to compare the result of a recipe with an item from the inventory.
* Use case: "Would this new thing be better than what I have now?"
  • Loading branch information
inogenous authored Sep 16, 2023
1 parent 25f56fe commit bb0bdee
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 19 deletions.
7 changes: 7 additions & 0 deletions data/raw/keybindings.json
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,13 @@
{ "input_method": "keyboard_code", "key": "8", "mod": [ "shift" ] }
]
},
{
"type": "keybinding",
"id": "COMPARE",
"category": "CRAFTING",
"name": "Compare recipe to item in inventory",
"bindings": [ { "input_method": "keyboard_char", "key": "I" }, { "input_method": "keyboard_code", "key": "i", "mod": [ "shift" ] } ]
},
{
"type": "keybinding",
"id": "LEVEL_UP",
Expand Down
74 changes: 55 additions & 19 deletions src/crafting_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
#include "debug.h"
#include "display.h"
#include "flag.h"
#include "game_inventory.h"
#include "input.h"
#include "inventory.h"
#include "inventory_ui.h"
#include "item.h"
#include "item_factory.h"
#include "itype.h"
Expand Down Expand Up @@ -101,6 +103,8 @@ static std::string peek_related_recipe( const recipe *current, const recipe_subs
static int related_menu_fill( uilist &rmenu,
const std::vector<std::pair<itype_id, std::string>> &related_recipes,
const recipe_subset &available );
static item get_recipe_result_item( const recipe &rec, Character &crafter );
static void compare_recipe_with_item( const item &recipe_item, Character &crafter );

static std::string get_cat_unprefixed( const std::string_view prefixed_name )
{
Expand Down Expand Up @@ -567,6 +571,7 @@ static input_context make_crafting_context( bool highlight_unread_recipes )
ctxt.register_action( "SELECT" );
ctxt.register_action( "SCROLL_UP" );
ctxt.register_action( "SCROLL_DOWN" );
ctxt.register_action( "COMPARE" );
if( highlight_unread_recipes ) {
ctxt.register_action( "TOGGLE_RECIPE_UNREAD" );
ctxt.register_action( "MARK_ALL_RECIPES_READ" );
Expand Down Expand Up @@ -680,6 +685,30 @@ void recipe_result_info_cache::get_item_header( item &dummy_item, const int quan
}
}

static item get_recipe_result_item( const recipe &rec, Character &crafter )
{
item dummy_result = item( rec.result(), calendar::turn, item::default_charges_tag{} );
if( !rec.variant().empty() ) {
dummy_result.set_itype_variant( rec.variant() );
}
//Check if recipe result is a clothing item that can be properly fitted
if( dummy_result.has_flag( flag_VARSIZE ) && !dummy_result.has_flag( flag_FIT ) ) {
//Check if it can actually fit. If so, list the fitted info
item::sizing general_fit = dummy_result.get_sizing( crafter );
if( general_fit == item::sizing::small_sized_small_char ||
general_fit == item::sizing::human_sized_human_char ||
general_fit == item::sizing::big_sized_big_char ||
general_fit == item::sizing::ignore ) {
dummy_result.set_flag( flag_FIT );
}
}
if( dummy_result.count_by_charges() ) {
dummy_result.charges = 1;
}
dummy_result.set_var( "recipe_exemplar", rec.ident().str() );
return dummy_result;
}

item_info_data recipe_result_info_cache::get_result_data( const recipe *rec, const int batch_size,
int &scroll_pos, const catacurses::window &window )
{
Expand Down Expand Up @@ -710,31 +739,13 @@ item_info_data recipe_result_info_cache::get_result_data( const recipe *rec, con
std::vector<iteminfo> details_info;

//Make a temporary item for the result. NOTE: If the result would normally be in a container, this is not.
item dummy_result = item( rec->result(), calendar::turn, item::default_charges_tag{} );
item dummy_result = get_recipe_result_item( *rec, crafter );
std::string result_description;
if( dummy_result.is_null() ) {
result_description = rec->description.translated();
}
if( !rec->variant().empty() ) {
dummy_result.set_itype_variant( rec->variant() );
}
//Check if recipe result is a clothing item that can be properly fitted
if( dummy_result.has_flag( flag_VARSIZE ) && !dummy_result.has_flag( flag_FIT ) ) {
//Check if it can actually fit. If so, list the fitted info
item::sizing general_fit = dummy_result.get_sizing( crafter );
if( general_fit == item::sizing::small_sized_small_char ||
general_fit == item::sizing::human_sized_human_char ||
general_fit == item::sizing::big_sized_big_char ||
general_fit == item::sizing::ignore ) {
dummy_result.set_flag( flag_FIT );
}
}
bool result_uses_charges = dummy_result.count_by_charges();
int const makes_amount = rec->makes_amount();
if( result_uses_charges ) {
dummy_result.charges = 1;
}
dummy_result.set_var( "recipe_exemplar", rec->ident().str() );
item dummy_container;

//Several terms are used repeatedly in headers/descriptions, list them here for a single entry/translation point
Expand Down Expand Up @@ -1954,6 +1965,9 @@ const recipe *select_crafting_recipe( int &batch_size_out, const recipe_id &goto
recalc = true;
recalc_unread = highlight_unread_recipes;
}
} else if( action == "COMPARE" && selection_ok( current, line, false ) ) {
const item recipe_result = get_recipe_result_item( *current[line], crafter );
compare_recipe_with_item( recipe_result, crafter );
} else if( action == "HELP_KEYBINDINGS" ) {
// Regenerate keybinding tips
ui.mark_resize();
Expand Down Expand Up @@ -2093,6 +2107,28 @@ int related_menu_fill( uilist &rmenu,
return np_last;
}

static void compare_recipe_with_item( const item &recipe_item, Character &crafter )
{
inventory_pick_selector inv_s( crafter );

inv_s.add_character_items( crafter );
inv_s.set_title( _( "Compare" ) );
inv_s.set_hint( _( "Select item to compare with." ) );

if( inv_s.empty() ) {
popup( std::string( _( "There are no items to compare." ) ), PF_GET_KEY );
return;
}

do {
const item_location to_compare = inv_s.execute();
if( !to_compare ) {
break;
}
game_menus::inv::compare_items( recipe_item, *to_compare );
} while( true );
}

static bool query_is_yes( const std::string_view query )
{
const std::string_view subquery = query.substr( 2 );
Expand Down

0 comments on commit bb0bdee

Please sign in to comment.