Skip to content

Commit

Permalink
Reimplement comestible craft entitys properly
Browse files Browse the repository at this point in the history
-Handle permafood edge case
  • Loading branch information
ifreund committed Apr 5, 2019
1 parent 857ff8b commit 8e14b36
Show file tree
Hide file tree
Showing 16 changed files with 174 additions and 216 deletions.
2 changes: 1 addition & 1 deletion src/clzones.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ zone_type_id zone_manager::get_near_zone_type_for_item( const item &it,
const auto &it_food = it.is_food_container() ? it.contents.front() : it;

if( it_food.is_food() ) { // skip food without comestible, like MREs
if( it_food.type->comestible->comesttype == "DRINK" ) {
if( it_food.get_comestible()->comesttype == "DRINK" ) {
if( !preserves && it_food.goes_bad() && has_near( zone_type_id( "LOOT_PDRINK" ), where ) ) {
return zone_type_id( "LOOT_PDRINK" );
} else if( has_near( zone_type_id( "LOOT_DRINK" ), where ) ) {
Expand Down
34 changes: 17 additions & 17 deletions src/consumption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ int player::kcal_for( const item &comest ) const
}
kcal /= comest.recipe_charges;
} else {
kcal = comest.type->comestible->get_calories();
kcal = comest.get_comestible()->get_calories();
}

if( has_trait( trait_GIZZARD ) ) {
Expand Down Expand Up @@ -165,7 +165,7 @@ std::pair<int, int> player::fun_for( const item &comest ) const
}

// As float to avoid rounding too many times
float fun = comest.type->comestible->fun;
float fun = comest.get_comestible()->fun;
if( comest.has_flag( flag_MUSHY ) && fun > -5.0f ) {
fun = -5.0f; // defrosted MUSHY food is practicaly tastless or tastes off
}
Expand Down Expand Up @@ -218,8 +218,8 @@ std::pair<int, int> player::fun_for( const item &comest ) const
}

if( has_active_bionic( bio_taste_blocker ) &&
power_level > abs( comest.type->comestible->fun ) &&
comest.type->comestible->fun < 0 ) {
power_level > abs( comest.get_comestible()->fun ) &&
comest.get_comestible()->fun < 0 ) {
fun = 0;
}

Expand Down Expand Up @@ -259,7 +259,7 @@ std::map<vitamin_id, int> player::vitamins_from( const item &it ) const
{
std::map<vitamin_id, int> res;

if( !it.type->comestible ) {
if( !it.get_comestible() ) {
return res;
}

Expand All @@ -277,7 +277,7 @@ std::map<vitamin_id, int> player::vitamins_from( const item &it ) const
}
} else {
// if we're here, whatever is returned is going to be based on the item's defined stats
res = it.type->comestible->vitamins;
res = it.get_comestible()->vitamins;
std::list<trait_id> traits = mut_vitamin_absorb_modify( *this );
// traits modify the absorption of vitamins here
if( !traits.empty() ) {
Expand Down Expand Up @@ -420,7 +420,7 @@ morale_type player::allergy_type( const item &food ) const
ret_val<edible_rating> player::can_eat( const item &food ) const
{

const auto &comest = food.type->comestible;
const auto &comest = food.get_comestible();
if( !comest ) {
return ret_val<edible_rating>::make_failure( _( "That doesn't look edible." ) );
}
Expand Down Expand Up @@ -511,7 +511,7 @@ ret_val<edible_rating> player::will_eat( const item &food, bool interactive ) co
};

const bool saprophage = has_trait( trait_id( "SAPROPHAGE" ) );
const auto &comest = food.type->comestible;
const auto &comest = food.get_comestible();

if( food.rotten() ) {
const bool saprovore = has_trait( trait_id( "SAPROVORE" ) );
Expand Down Expand Up @@ -612,13 +612,13 @@ bool player::eat( item &food, bool force )

const bool hibernate = has_active_mutation( trait_id( "HIBERNATE" ) );
const int nutr = nutrition_for( food );
const int quench = food.type->comestible->quench;
const int quench = food.get_comestible()->quench;
const bool spoiled = food.rotten();

// The item is solid food
const bool chew = food.type->comestible->comesttype == "FOOD" || food.has_flag( "USE_EAT_VERB" );
const bool chew = food.get_comestible()->comesttype == "FOOD" || food.has_flag( "USE_EAT_VERB" );
// This item is a drink and not a solid food (and not a thick soup)
const bool drinkable = !chew && food.type->comestible->comesttype == "DRINK";
const bool drinkable = !chew && food.get_comestible()->comesttype == "DRINK";
// If neither of the above is true then it's a drug and shouldn't get mealtime penalty/bonus

if( hibernate &&
Expand Down Expand Up @@ -750,9 +750,9 @@ bool player::eat( item &food, bool force )
}
}

if( item::find_type( food.type->comestible->tool )->tool ) {
if( item::find_type( food.get_comestible()->tool )->tool ) {
// Tools like lighters get used
use_charges( food.type->comestible->tool, 1 );
use_charges( food.get_comestible()->tool, 1 );
}

if( has_bionic( bio_ethanol ) && food.type->can_use( "ALCOHOL" ) ) {
Expand All @@ -766,7 +766,7 @@ bool player::eat( item &food, bool force )
}

if( has_active_bionic( bio_taste_blocker ) ) {
charge_power( -abs( food.type->comestible->fun ) );
charge_power( -abs( food.get_comestible()->fun ) );
}

if( food.has_flag( "CANNIBALISM" ) ) {
Expand Down Expand Up @@ -874,8 +874,8 @@ bool player::eat( item &food, bool force )

// chance to become parasitised
if( !( has_bionic( bio_digestion ) || has_trait( trait_id( "PARAIMMUNE" ) ) ) ) {
if( food.type->comestible->parasites > 0 && !food.has_flag( "NO_PARASITES" ) &&
one_in( food.type->comestible->parasites ) ) {
if( food.get_comestible()->parasites > 0 && !food.has_flag( "NO_PARASITES" ) &&
one_in( food.get_comestible()->parasites ) ) {
switch( rng( 0, 3 ) ) {
case 0:
if( !has_trait( trait_id( "EATHEALTH" ) ) ) {
Expand Down Expand Up @@ -940,7 +940,7 @@ void player::consume_effects( const item &food )
debugmsg( "called player::consume_effects with non-comestible" );
return;
}
const auto &comest = *food.type->comestible;
const auto &comest = *food.get_comestible();

const int capacity = stomach_capacity();
if( has_trait( trait_id( "THRESH_PLANT" ) ) && food.type->can_use( "PLANTBLECH" ) ) {
Expand Down
40 changes: 20 additions & 20 deletions src/crafting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,21 +467,29 @@ static item *set_item_inventory( player &p, item &newit )
return ret_val;
}

static void return_all_components_for_craft( player &p, std::list<item> &used )
static void return_all_components_for_craft( player &p, std::list<item> &used,
const double &relative_rot )
{
// Force add here since the craft item is removed immediately after
for( item &it : used ) {
// If the product doesn't rot, don't touch component rot.
if( relative_rot != 0.0 ) {
it.set_relative_rot( relative_rot );
}
set_item_inventory( p, it );
}
}

static void return_some_components_for_craft( player &p, std::list<item> &used )
static void return_some_components_for_craft( player &p, std::list<item> &used,
const double &relative_rot )
{
for( std::list<item>::iterator it = used.begin(); it != used.end(); ++it ) {
// Force add here since the craft item is removed in the same turn
// Each component has a 50% chance of being returned
// Never return the first component
if( it != used.begin() && one_in( 2 ) ) {
// If the product doesn't rot, don't touch component rot.
if( relative_rot != 0.0 ) {
it->set_relative_rot( relative_rot );
}
set_item_inventory( p, *it );
}
}
Expand Down Expand Up @@ -630,29 +638,21 @@ void player::complete_craft( item &craft )
}

std::list<item> &used = craft.components;
const double relative_rot = craft.get_relative_rot();

// Messed up badly; waste some components.
if( making.difficulty != 0 && diff_roll > skill_roll * ( 1 + 0.1 * rng( 1, 5 ) ) ) {
add_msg( m_bad, _( "You fail to make the %s, and waste some materials." ), making.result_name() );
return_some_components_for_craft( *this, used );
return_some_components_for_craft( *this, used, relative_rot );
return;
// Messed up slightly; no components wasted.
} else if( diff_roll > skill_roll ) {
add_msg( m_neutral, _( "You fail to make the %s, but don't waste any materials." ),
making.result_name() );
return_all_components_for_craft( *this, used );
return_all_components_for_craft( *this, used, relative_rot );
return;
}

// Take the relative rot of the most rotten component
double max_relative_rot = 0.0;
for( const item &it : used ) {
if( !it.goes_bad() ) {
continue;
}
max_relative_rot = std::max( max_relative_rot, it.get_relative_rot() );
}

// Set up the new item, and assign an inventory letter if available
std::vector<item> newits = making.create_results( batch_size );

Expand Down Expand Up @@ -736,8 +736,8 @@ void player::complete_craft( item &craft )
// if a component item has "cooks_like" it will be replaced by that item as a component
for( item &comp : used ) {
// only comestibles have cooks_like. any other type of item will throw an exception, so filter those out
if( comp.is_comestible() && !comp.type->comestible->cooks_like.empty() ) {
comp = item( comp.type->comestible->cooks_like, comp.birthday(), comp.charges );
if( comp.is_comestible() && !comp.get_comestible()->cooks_like.empty() ) {
comp = item( comp.get_comestible()->cooks_like, comp.birthday(), comp.charges );
}
}
// byproducts get stored as a "component" but with a byproduct flag for consumption purposes
Expand All @@ -755,12 +755,12 @@ void player::complete_craft( item &craft )
}

if( newit.goes_bad() ) {
newit.set_relative_rot( max_relative_rot );
newit.set_relative_rot( relative_rot );
} else {
if( newit.is_container() ) {
for( item &in : newit.contents ) {
if( in.goes_bad() ) {
in.set_relative_rot( max_relative_rot );
in.set_relative_rot( relative_rot );
}
}
}
Expand Down Expand Up @@ -790,7 +790,7 @@ void player::complete_craft( item &craft )
std::vector<item> bps = making.create_byproducts( batch_size );
for( auto &bp : bps ) {
if( bp.goes_bad() ) {
bp.set_relative_rot( max_relative_rot );
bp.set_relative_rot( relative_rot );
}
if( bp.is_food() ) {
if( should_heat ) {
Expand Down
6 changes: 3 additions & 3 deletions src/dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ bool game::dump_stats( const std::string &what, dump_mode mode,
r.push_back( to_string( obj.volume() / units::legacy_volume_factor ) );
r.push_back( to_string( to_gram( obj.weight() ) ) );
r.push_back( to_string( obj.type->stack_size ) );
r.push_back( to_string( obj.type->comestible->get_calories() ) );
r.push_back( to_string( obj.type->comestible->quench ) );
r.push_back( to_string( obj.type->comestible->healthy ) );
r.push_back( to_string( obj.get_comestible()->get_calories() ) );
r.push_back( to_string( obj.get_comestible()->quench ) );
r.push_back( to_string( obj.get_comestible()->healthy ) );
auto vits = g->u.vitamins_from( obj );
for( const auto &v : vitamin::all() ) {
r.push_back( to_string( vits[ v.first ] ) );
Expand Down
4 changes: 2 additions & 2 deletions src/faction_camp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3434,7 +3434,7 @@ bool basecamp::distribute_food()
g->m.add_item_or_charges( litter_spread, i, false );
i = comest;
}
if( i.is_comestible() && ( i.rotten() || i.type->comestible->fun < -6 ) ) {
if( i.is_comestible() && ( i.rotten() || i.get_comestible()->fun < -6 ) ) {
keep_me.push_back( i );
} else if( i.is_food() ) {
double rot_multip;
Expand All @@ -3446,7 +3446,7 @@ bool basecamp::distribute_food()
} else {
rot_multip = quick_rot;
}
total += i.type->comestible->get_calories() * rot_multip * i.count();
total += i.get_comestible()->get_calories() * rot_multip * i.count();
} else {
keep_me.push_back( i );
}
Expand Down
2 changes: 1 addition & 1 deletion src/game_inventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ class comestible_inventory_preset : public inventory_selector_preset

const islot_comestible &get_edible_comestible( const item &it ) const {
if( it.is_comestible() && p.can_eat( it ).success() ) {
return *it.type->comestible;
return *it.get_comestible();
}
static const islot_comestible dummy {};
return dummy;
Expand Down
6 changes: 3 additions & 3 deletions src/iexamine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4203,11 +4203,11 @@ void smoker_finalize( player &, const tripoint &examp, const time_point &start_t

for( size_t i = 0; i < items.size(); i++ ) {
auto &item_it = items[i];
if( item_it.type->comestible ) {
if( item_it.type->comestible->smoking_result.empty() ) {
if( item_it.get_comestible() ) {
if( item_it.get_comestible()->smoking_result.empty() ) {
item_it.unset_flag( "SMOKING" );
} else {
item result( item_it.type->comestible->smoking_result, start_time + 6_hours, item_it.charges );
item result( item_it.get_comestible()->smoking_result, start_time + 6_hours, item_it.charges );

// Set flag to tell set_relative_rot() to calc from bday not now
result.set_flag( "SMOKING_RESULT" );
Expand Down
Loading

0 comments on commit 8e14b36

Please sign in to comment.