Skip to content

Commit 0c81895

Browse files
committed
Allow variants for brewing and composting results
It would probably be nicer to use a struct instead of a pair here, but not that much.
1 parent 24dc322 commit 0c81895

File tree

7 files changed

+90
-50
lines changed

7 files changed

+90
-50
lines changed

doc/JSON/ITEM.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,8 @@ If an item is BREWABLE, it can be placed in a vat and will ferment into a differ
10021002
"name": { "str_sp": "whiskey wort" },
10031003
"description": "Unfermented whiskey. The base of a fine drink. Not the traditional preparation, but you don't have the time. You need to put it in a fermenting vat to brew it.",
10041004
"brew_time": "7 days", // A time duration: how long the fermentation will take.
1005-
"brew_results": [ "wash_whiskey", "yeast" ], // IDs with a multiplier for the amount of results per charge of the brewable items.
1005+
"brew_results": [ "wash_whiskey", { "item": "yeast", "variant": "foo", "count": 3 } ], // IDs with a multiplier for the amount of results per charge of the brewable items.
1006+
"brew_results": { "wash_whiskey": 2, "yeast": 3 }, // Alternate format
10061007
...
10071008
//comestible fields
10081009
```
@@ -1024,6 +1025,7 @@ If an item is BREWABLE, it can be placed in a vat and will ferment into a differ
10241025
"charges": 1,
10251026
"compost_time": "60 days", // the amount of time required to fully compost this item
10261027
"compost_results": { "fermented_fertilizer_liquid": 1, "biogas": 250 }, //item IDs and quantities resulting from compost
1028+
"compost_results": [ "fermented_fertilizer_liquid", { "item": "biogas", "variant": "foo", "count": "250" } ], // alternate format
10271029
...
10281030
//COMESTIBLE fields
10291031
```

src/iexamine.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4011,22 +4011,24 @@ void iexamine::fvat_full( Character &you, const tripoint_bub_ms &examp )
40114011
}
40124012

40134013
if( query_yn( _( "Finish brewing?" ) ) ) {
4014-
const std::map<itype_id, int> results = brew_i.brewing_results();
4014+
const std::map<std::pair<itype_id, std::string>, int> &results = brew_i.brewing_results();
40154015
const int count = brew_i.count();
40164016
const time_point birthday = brew_i.birthday();
40174017

40184018
here.i_clear( examp );
4019-
for( const std::pair<const itype_id, int> &result : results ) {
4019+
for( const std::pair<const std::pair<itype_id, std::string>, int> &result : results ) {
40204020
int amount = result.second * count;
4021+
const itype_id &item_type = result.first.first;
40214022
// TODO: Different age based on settings
4022-
item booze( result.first, birthday );
4023-
if( result.first->phase == phase_id::LIQUID ) {
4023+
item booze( item_type, birthday );
4024+
booze.set_itype_variant( result.first.second );
4025+
if( item_type->phase == phase_id::LIQUID ) {
40244026
booze.charges = amount;
40254027
here.add_item( examp, booze );
4026-
add_msg( _( "The %s is now ready for bottling." ), result.first->nname( amount ) );
4028+
add_msg( _( "The %s is now ready for bottling." ), item_type->nname( amount ) );
40274029
} else {
40284030
you.i_add_or_drop( booze, amount );
4029-
add_msg( _( "You remove the %s from the vat." ), result.first->nname( amount ) );
4031+
add_msg( _( "You remove the %s from the vat." ), item_type->nname( amount ) );
40304032
}
40314033
}
40324034

@@ -4253,18 +4255,20 @@ void iexamine::compost_full( Character &you, const tripoint_bub_ms &examp )
42534255
}
42544256
if( to_days<int>( progress ) >= 30 && gas_gatherable >= 1 ) {
42554257
if( query_yn( _( "Gather biogas? Can't stop once releasing started." ) ) ) {
4256-
const std::map<itype_id, int> results = compost_i.composting_results();
4258+
const std::map<std::pair<itype_id, std::string>, int> &results = compost_i.composting_results();
42574259
const int count = compost_i.count();
42584260
const time_point gas_birthday = compost_i.birthday();
42594261
if( !max_gas_gatherable ) {
42604262
add_msg( _( "No biogas gathered." ) );
42614263
} else {
4262-
for( const std::pair<const itype_id, int> &result : results ) {
4263-
item biogas( result.first, gas_birthday );
4264+
for( const std::pair<const std::pair<itype_id, std::string>, int> &result : results ) {
4265+
4266+
item biogas( result.first.first, gas_birthday );
4267+
biogas.set_itype_variant( result.first.second );
42644268
// 40 L biogas for 1 KG of biomass over the whole anaerobic digestion process.
42654269
// 1 unit of biomass(0.5 KG) for 80 units(0.25 L for each unit) of biogas.
42664270
int gas_amount = count * max_gas_gatherable * 80 / 30;
4267-
if( result.first->phase == phase_id::GAS ) {
4271+
if( result.first.first->phase == phase_id::GAS ) {
42684272
if( !you.can_pickVolume_partial( biogas ) ) {
42694273
add_msg( _( "You released some biogas from the tank." ) );
42704274
} else {
@@ -4285,20 +4289,22 @@ void iexamine::compost_full( Character &you, const tripoint_bub_ms &examp )
42854289
}
42864290

42874291
if( query_yn( _( "Finish fermenting?" ) ) ) {
4288-
const std::map<itype_id, int> results = compost_i.composting_results();
4292+
const std::map<std::pair<itype_id, std::string>, int> &results = compost_i.composting_results();
42894293
const int count = compost_i.count();
42904294
const time_point birthday = compost_i.birthday();
42914295

42924296
here.i_clear( examp );
4293-
for( const std::pair<const itype_id, int> &result : results ) {
4297+
for( const std::pair<const std::pair<itype_id, std::string>, int> &result : results ) {
42944298
int amount = result.second * count;
42954299
// TODO: Different age based on settings
4296-
item compost( result.first, birthday );
4297-
if( result.first->phase == phase_id::LIQUID ) {
4300+
const itype_id &item_type = result.first.first;
4301+
item compost( item_type, birthday );
4302+
compost.set_itype_variant( result.first.second );
4303+
if( item_type->phase == phase_id::LIQUID ) {
42984304
compost.charges = amount;
42994305
here.add_item( examp, compost );
4300-
add_msg( _( "The %s is now ready for use." ), result.first->nname( amount ) );
4301-
} else if( result.first->phase == phase_id::GAS ) {
4306+
add_msg( _( "The %s is now ready for use." ), item_type->nname( amount ) );
4307+
} else if( item_type->phase == phase_id::GAS ) {
43024308
int gas_amount = count * max_gas_gatherable * 80 / 30;
43034309
if( !gas_amount || !you.can_pickVolume_partial( compost ) ) {
43044310
add_msg( _( "You released some biogas from the tank." ) );
@@ -4309,7 +4315,7 @@ void iexamine::compost_full( Character &you, const tripoint_bub_ms &examp )
43094315
}
43104316
} else {
43114317
you.i_add_or_drop( compost, amount );
4312-
add_msg( _( "You removed the %s from the tank." ), result.first->nname( amount ) );
4318+
add_msg( _( "You removed the %s from the tank." ), item_type->nname( amount ) );
43134319
}
43144320
}
43154321

src/item.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,9 +2283,9 @@ time_duration item::brewing_time() const
22832283
return is_brewable() ? type->brewable->time * calendar::season_from_default_ratio() : 0_turns;
22842284
}
22852285

2286-
const std::map<itype_id, int> &item::brewing_results() const
2286+
const std::map<std::pair<itype_id, std::string>, int> &item::brewing_results() const
22872287
{
2288-
static const std::map<itype_id, int> nulresult{};
2288+
static const std::map<std::pair<itype_id, std::string>, int> nulresult{};
22892289
return is_brewable() ? type->brewable->results : nulresult;
22902290
}
22912291

@@ -2294,9 +2294,9 @@ time_duration item::composting_time() const
22942294
return is_compostable() ? type->compostable->time * calendar::season_from_default_ratio() : 0_turns;
22952295
}
22962296

2297-
const std::map<itype_id, int> &item::composting_results() const
2297+
const std::map<std::pair<itype_id, std::string>, int> &item::composting_results() const
22982298
{
2299-
static const std::map<itype_id, int> nulresult{};
2299+
static const std::map<std::pair<itype_id, std::string>, int> nulresult{};
23002300
return is_compostable() ? type->compostable->results : nulresult;
23012301
}
23022302

src/item.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,12 +1219,12 @@ class item : public visitable
12191219
/** Time for this item to be fully fermented. */
12201220
time_duration brewing_time() const;
12211221
/** The results of fermenting this item. */
1222-
const std::map<itype_id, int> &brewing_results() const;
1222+
const std::map<std::pair<itype_id, std::string>, int> &brewing_results() const;
12231223

12241224
/** Time for this item to be fully fermented. */
12251225
time_duration composting_time() const;
12261226
/** The results of fermenting this item. */
1227-
const std::map<itype_id, int> &composting_results() const;
1227+
const std::map<std::pair<itype_id, std::string>, int> &composting_results() const;
12281228

12291229
/**
12301230
* Detonates the item and adds remains (if any) to drops.

src/item_factory.cpp

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2490,9 +2490,17 @@ void Item_factory::check_definitions() const
24902490
msg += "empty product list\n";
24912491
}
24922492

2493-
for( const std::pair<const itype_id, int> &b : type->brewable->results ) {
2494-
if( !has_template( b.first ) ) {
2495-
msg += string_format( "invalid result id %s\n", b.first.c_str() );
2493+
for( const std::pair<const std::pair<itype_id, std::string>, int> &b : type->brewable->results ) {
2494+
if( !has_template( b.first.first ) ) {
2495+
msg += string_format( "invalid result id %s\n", b.first.first.c_str() );
2496+
}
2497+
const std::vector<itype_variant_data> &variants = b.first.first->variants;
2498+
const auto has_variant = [&b]( const itype_variant_data & variant ) {
2499+
return b.first.second == variant.id;
2500+
};
2501+
if( !b.first.second.empty() &&
2502+
std::find_if( variants.begin(), variants.end(), has_variant ) == variants.end() ) {
2503+
msg += string_format( "Invalid variant %s for result %s\n", b.first.second, b.first.first.c_str() );
24962504
}
24972505
}
24982506
}
@@ -2505,9 +2513,18 @@ void Item_factory::check_definitions() const
25052513
msg += "empty product list\n";
25062514
}
25072515

2508-
for( const std::pair<const itype_id, int> &b : type->compostable->results ) {
2509-
if( !has_template( b.first ) ) {
2510-
msg += string_format( "invalid result id %s\n", b.first.c_str() );
2516+
for( const std::pair<const std::pair<itype_id, std::string>, int> &b :
2517+
type->compostable->results ) {
2518+
if( !has_template( b.first.first ) ) {
2519+
msg += string_format( "invalid result id %s\n", b.first.first.c_str() );
2520+
}
2521+
const std::vector<itype_variant_data> &variants = b.first.first->variants;
2522+
const auto has_variant = [&b]( const itype_variant_data & variant ) {
2523+
return b.first.second == variant.id;
2524+
};
2525+
if( !b.first.second.empty() &&
2526+
std::find_if( variants.begin(), variants.end(), has_variant ) == variants.end() ) {
2527+
msg += string_format( "Invalid variant %s for result %s\n", b.first.second, b.first.first.c_str() );
25112528
}
25122529
}
25132530
}
@@ -3420,28 +3437,41 @@ void islot_comestible::deserialize( const JsonObject &jo )
34203437
}
34213438
}
34223439

3440+
struct generic_result_reader : generic_typed_reader<generic_result_reader> {
3441+
static constexpr bool read_objects = true;
3442+
std::pair<std::pair<itype_id, std::string>, int> get_next( const JsonValue &jv ) const {
3443+
std::pair<std::pair<itype_id, std::string>, int> ret;
3444+
// "yeast": 2,
3445+
if( const JsonMember *jm = dynamic_cast<const JsonMember *>( &jv ) ) {
3446+
ret.first.first = itype_id( jm->name() );
3447+
jm->read( ret.second );
3448+
return ret;
3449+
}
3450+
// "yeast"
3451+
if( jv.test_string() ) {
3452+
jv.read( ret.first.first );
3453+
ret.second = 1;
3454+
return ret;
3455+
}
3456+
// { "item": "yeast", "count": 2, "variant": "foo" }
3457+
JsonObject jo = jv.get_object();
3458+
mandatory( jo, false, "item", ret.first.first );
3459+
optional( jo, false, "variant", ret.first.second, "" );
3460+
optional( jo, false, "count", ret.second, 1 );
3461+
return ret;
3462+
}
3463+
};
3464+
34233465
void islot_brewable::deserialize( const JsonObject &jo )
34243466
{
34253467
optional( jo, was_loaded, "brew_time", time, 1_turns );
3426-
if( jo.has_array( "brew_results" ) ) {
3427-
for( std::string entry : jo.get_string_array( "brew_results" ) ) {
3428-
results[itype_id( entry )] = 1;
3429-
}
3430-
} else {
3431-
mandatory( jo, was_loaded, "brew_results", results );
3432-
}
3468+
mandatory( jo, was_loaded, "brew_results", results, generic_result_reader{} );
34333469
}
34343470

34353471
void islot_compostable::deserialize( const JsonObject &jo )
34363472
{
34373473
optional( jo, was_loaded, "compost_time", time, 1_turns );
3438-
if( jo.has_array( "compost_results" ) ) {
3439-
for( std::string entry : jo.get_string_array( "compost_results" ) ) {
3440-
results[itype_id( entry )] = 1;
3441-
}
3442-
} else {
3443-
mandatory( jo, was_loaded, "compost_results", results );
3444-
}
3474+
mandatory( jo, was_loaded, "compost_results", results, generic_result_reader{} );
34453475
}
34463476

34473477
void islot_seed::deserialize( const JsonObject &jo )

src/item_info.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3828,11 +3828,12 @@ void item::final_info( std::vector<iteminfo> &info, const iteminfo_query *parts,
38283828
}
38293829
}
38303830
if( parts->test( iteminfo_parts::DESCRIPTION_BREWABLE_PRODUCTS ) ) {
3831-
for( const std::pair<const itype_id, int> &res : brewed.brewing_results() ) {
3831+
for( const std::pair<const std::pair<itype_id, std::string>, int> &res :
3832+
brewed.brewing_results() ) {
38323833
info.emplace_back( "DESCRIPTION",
38333834
string_format( _( "* Fermenting this will produce "
38343835
"<neutral>%s</neutral>." ),
3835-
res.first->nname( res.second ) ) );
3836+
res.first.first->nname( res.second ) ) );
38363837
}
38373838
}
38383839
}
@@ -3858,11 +3859,12 @@ void item::final_info( std::vector<iteminfo> &info, const iteminfo_query *parts,
38583859
}
38593860
}
38603861
if( parts->test( iteminfo_parts::DESCRIPTION_COMPOSTABLE_PRODUCTS ) ) {
3861-
for( const std::pair<const itype_id, int> &res : composted.composting_results() ) {
3862+
for( const std::pair<const std::pair<itype_id, std::string>, int> &res :
3863+
composted.composting_results() ) {
38623864
info.emplace_back( "DESCRIPTION",
38633865
string_format( _( "* Fermenting this will produce "
38643866
"<neutral>%s</neutral>." ),
3865-
res.first->nname( res.second ) ) );
3867+
res.first.first->nname( res.second ) ) );
38663868
}
38673869
}
38683870
}

src/itype.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ struct islot_comestible {
255255

256256
struct islot_brewable {
257257
/** What are the results of fermenting this item? */
258-
std::map<itype_id, int> results;
258+
std::map<std::pair<itype_id, std::string>, int> results;
259259

260260
/** How long for this brew to ferment. */
261261
time_duration time = 0_turns;
@@ -266,7 +266,7 @@ struct islot_brewable {
266266

267267
struct islot_compostable {
268268
/** What are the results of fermenting this item? */
269-
std::map<itype_id, int> results;
269+
std::map<std::pair<itype_id, std::string>, int> results;
270270

271271
/** How long for this compost to ferment. */
272272
time_duration time = 0_turns;

0 commit comments

Comments
 (0)