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

Properly show variant's prefix/suffix in the crafting menu #78904

Merged
merged 2 commits into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
25 changes: 25 additions & 0 deletions data/mods/TEST_DATA/items.json
Original file line number Diff line number Diff line change
Expand Up @@ -1589,6 +1589,31 @@
}
]
},
{
"id": "test_xl_waist_apron_long",
"type": "GENERIC",
"name": { "str": "long waist apron" },
"copy-from": "test_waist_apron_long",
"extend": { "flags": [ "OVERSIZE", "PREFIX_XL" ] },
"//": "the variants are not copy-from'd at the time of writing so let's make some",
"variants": [
{
"id": "generic_apron_cotton",
"name": { "str": "long waist apron" },
"description": "It's colored white, like the ones commonly used by chefs, professional or otherwise.",
"weight": 50,
"append": true
},
{
"id": "pink_apron_cotton",
"name": { "str": "pink long waist apron" },
"description": "It's colored neon pink, commonly used by women or men who like pink.",
"color": "pink",
"weight": 3,
"append": true
}
]
},
{
"id": "test_umbrella",
"type": "GENERIC",
Expand Down
6 changes: 6 additions & 0 deletions data/mods/TEST_DATA/recipes.json
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@
"autolearn": true,
"using": [ [ "tailoring_cotton_patchwork", 6 ] ]
},
{
"//": "Variant version with XL prefix",
"result": "test_xl_waist_apron_long",
"type": "recipe",
"copy-from": "test_waist_apron_long_pink_apron_cotton"
},
{
"result": "test_200_kcal",
"type": "recipe",
Expand Down
14 changes: 12 additions & 2 deletions src/item_tname.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,26 @@ constexpr uint64_t tname_conditional_bits = // TODO: fine grain?
1ULL << static_cast<size_t>( tname::segments::COMPONENTS ) |
1ULL << static_cast<size_t>( tname::segments::TAGS ) |
1ULL << static_cast<size_t>( tname::segments::VARS );
constexpr uint64_t item_name_bits = // item prefix + item name + item suffix
constexpr uint64_t base_item_name_bits =
1ULL << static_cast<size_t>( tname::segments::CUSTOM_ITEM_PREFIX ) |
1ULL << static_cast<size_t>( tname::segments::TYPE ) |
1ULL << static_cast<size_t>( tname::segments::CUSTOM_ITEM_SUFFIX );
constexpr uint64_t variant_bits =
1ULL << static_cast<size_t>( tname::segments::VARIANT );
constexpr segment_bitset default_tname( default_tname_bits );
constexpr segment_bitset unprefixed_tname( default_tname_bits & ~tname_prefix_bits );
constexpr segment_bitset tname_sort_key( default_tname_bits & ~tname_unsortable_bits );
constexpr segment_bitset tname_contents( tname_contents_bits );
constexpr segment_bitset tname_conditional( tname_conditional_bits );
constexpr segment_bitset item_name( item_name_bits );
// Name for an abstract base item of a given class, not any specific one.
// Often used in crafting UI and similar.
// For example in the sentence "To make some 'XL socks' I will need to cut up a 'blanket'",
// when we don't care which color (read: variant) 'XL socks' we want or 'blanket' we have.
constexpr segment_bitset base_item_name( base_item_name_bits );
// Name of a specific item in the game world, carries the item identity, and will not
// change in a normal playthrough except through exordinary means (e.g. via `iuse_transform`).
// E.g. "XL green socks" (notably, not "|. XL green socks (filthy)")
constexpr segment_bitset item_identity_name( base_item_name_bits | variant_bits );

} // namespace tname

Expand Down
22 changes: 13 additions & 9 deletions src/recipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1218,17 +1218,21 @@ std::string recipe::result_name( const bool decorated ) const
{
std::string name;
if( !name_.empty() ) {
// if the recipe has an explicit name (such as for proficiency training) - use that
name = name_.translated();
} else if( !variant().empty() ) {
auto iter_var = std::find_if( result_->variants.begin(), result_->variants.end(),
[this]( const itype_variant_data & itvar ) {
return itvar.id == variant();
} );
if( iter_var != result_->variants.end() ) {
name = iter_var->alt_name.translated();
}
} else {
name = item::tname( result_, 1, tname::item_name );
// Names are tricky, so we have to create a temporary fake result item to get one.
// As of 2025-01-01 there's no better way around this.
item temp_item( result_ );
// Use generic item name by default.
tname::segment_bitset segs = tname::base_item_name;
if( !variant().empty() ) {
// ..but if the recipe calls for a specific varaint - then use that variant.
// Note that `temp_item` is likely to already have a random variant set at the time of creation.
temp_item.set_itype_variant( variant() );
segs = tname::item_identity_name;
}
name = temp_item.tname( 1, segs );
}
if( decorated &&
uistate.favorite_recipes.find( this->ident() ) != uistate.favorite_recipes.end() ) {
Expand Down
16 changes: 8 additions & 8 deletions src/requirements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@ std::string tool_comp::to_string( const int batch, const int ) const
//~ %1$s: tool name, %2$d: charge requirement
return string_format( npgettext( "requirement", "%1$s (%2$d charge)", "%1$s (%2$d charges)",
charge_total ),
item::tname( type, 1, tname::item_name ), charge_total );
item::tname( type, 1, tname::base_item_name ), charge_total );
} else {
return item::tname( type, std::abs( count ), tname::item_name );
return item::tname( type, std::abs( count ), tname::base_item_name );
}
}

Expand All @@ -176,33 +176,33 @@ std::string item_comp::to_string( const int batch, const int avail ) const
return string_format( npgettext( "requirement", "%2$d %1$s (have infinite)",
"%2$d %1$s (have infinite)",
c ),
item_temp.tname( 1, tname::item_name ), c );
item_temp.tname( 1, tname::base_item_name ), c );
} else if( avail > 0 ) {
//~ %1$s: item name, %2$d: charge requirement, %3%d: available charges
return string_format( npgettext( "requirement", "%2$d %1$s (have %3$d)",
"%2$d %1$s (have %3$d)", c ),
item_temp.tname( 1, tname::item_name ), c, avail );
item_temp.tname( 1, tname::base_item_name ), c, avail );
} else {
//~ %1$s: item name, %2$d: charge requirement
return string_format( npgettext( "requirement", "%2$d %1$s", "%2$d %1$s", c ),
item_temp.tname( 1, tname::item_name ), c );
item_temp.tname( 1, tname::base_item_name ), c );
}
} else {
if( avail == item::INFINITE_CHARGES ) {
//~ %1$s: item name, %2$d: required count
return string_format( npgettext( "requirement", "%2$d %1$s (have infinite)",
"%2$d %1$s (have infinite)",
c ),
item_temp.tname( c, tname::item_name ), c );
item_temp.tname( c, tname::base_item_name ), c );
} else if( avail > 0 ) {
//~ %1$s: item name, %2$d: required count, %3%d: available count
return string_format( npgettext( "requirement", "%2$d %1$s (have %3$d)",
"%2$d %1$s (have %3$d)", c ),
item_temp.tname( c, tname::item_name ), c, avail );
item_temp.tname( c, tname::base_item_name ), c, avail );
} else {
//~ %1$s: item name, %2$d: required count
return string_format( npgettext( "requirement", "%2$d %1$s", "%2$d %1$s", c ),
item_temp.tname( c, tname::item_name ), c );
item_temp.tname( c, tname::base_item_name ), c );
}
}
}
Expand Down
24 changes: 18 additions & 6 deletions tests/crafting_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ static const recipe_id recipe_test_tallow2( "test_tallow2" );
static const recipe_id recipe_test_waist_apron_long( "test_waist_apron_long" );
static const recipe_id
recipe_test_waist_apron_long_pink_apron_cotton( "test_waist_apron_long_pink_apron_cotton" );
static const recipe_id
recipe_test_xl_waist_apron_long_pink_apron_cotton( "test_xl_waist_apron_long_pink_apron_cotton" );
static const recipe_id recipe_vambrace_larmor( "vambrace_larmor" );
static const recipe_id recipe_water_clean( "water_clean" );

Expand Down Expand Up @@ -2247,11 +2249,12 @@ TEST_CASE( "variant_crafting_recipes", "[crafting][slow]" )
tools.emplace_back( "scissors" );
tools.insert( tools.end(), 10, item( "sheet_cotton" ) );
tools.insert( tools.end(), 10, item( "thread" ) );
prep_craft( recipe_test_waist_apron_long, tools, true );
actually_test_craft( recipe_test_waist_apron_long, INT_MAX, 10 );
const recipe_id apron_recipe = recipe_test_waist_apron_long;
prep_craft( apron_recipe, tools, true );
actually_test_craft( apron_recipe, INT_MAX, 10 );
item_location apron = player_character.get_wielded_item();

REQUIRE( apron->type->get_id() == recipe_test_waist_apron_long->result() );
REQUIRE( apron->type->get_id() == apron_recipe->result() );
REQUIRE( apron->has_itype_variant() );

if( variant_counts.count( apron->itype_variant().id ) == 0 ) {
Expand All @@ -2275,11 +2278,12 @@ TEST_CASE( "variant_crafting_recipes", "[crafting][slow]" )
tools.emplace_back( "scissors" );
tools.insert( tools.end(), 10, item( "sheet_cotton" ) );
tools.insert( tools.end(), 10, item( "thread" ) );
prep_craft( recipe_test_waist_apron_long_pink_apron_cotton, tools, true );
actually_test_craft( recipe_test_waist_apron_long_pink_apron_cotton, INT_MAX, 10 );
const recipe_id apron_recipe = recipe_test_xl_waist_apron_long_pink_apron_cotton;
prep_craft( apron_recipe, tools, true );
actually_test_craft( apron_recipe, INT_MAX, 10 );
item_location apron = player_character.get_wielded_item();

REQUIRE( apron->type->get_id() == recipe_test_waist_apron_long_pink_apron_cotton->result() );
REQUIRE( apron->type->get_id() == apron_recipe->result() );
REQUIRE( apron->has_itype_variant() );

if( apron->itype_variant().id == "pink_apron_cotton" ) {
Expand All @@ -2288,6 +2292,14 @@ TEST_CASE( "variant_crafting_recipes", "[crafting][slow]" )
}
CHECK( specific_variant_count == max_iters );
}
SECTION( "recipe names" ) {
const recipe_id basic_recipe = recipe_test_waist_apron_long;
CHECK( basic_recipe.obj().result_name() == "long waist apron" );
const recipe_id variant_recipe = recipe_test_waist_apron_long_pink_apron_cotton;
CHECK( variant_recipe.obj().result_name() == "pink long waist apron" );
const recipe_id variant_prefix_recipe = recipe_test_xl_waist_apron_long_pink_apron_cotton;
CHECK( variant_prefix_recipe.obj().result_name() == "XL pink long waist apron" );
}
}

TEST_CASE( "pseudo_tools_in_crafting_inventory", "[crafting][tools]" )
Expand Down
Loading