Skip to content

Commit

Permalink
Merge pull request #28937 from ifreund/craft-entity
Browse files Browse the repository at this point in the history
[RDY] Initial craft entity implementation
  • Loading branch information
kevingranade authored Apr 9, 2019
2 parents 986a05e + fbb59eb commit 7225789
Show file tree
Hide file tree
Showing 31 changed files with 440 additions and 279 deletions.
5 changes: 5 additions & 0 deletions data/json/item_actions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1028,5 +1028,10 @@
"type": "item_action",
"id": "PANACEA",
"name": "Take"
},
{
"type": "item_action",
"id": "CRAFT",
"name": "Work on craft"
}
]
14 changes: 14 additions & 0 deletions data/json/items/generic.json
Original file line number Diff line number Diff line change
Expand Up @@ -3007,5 +3007,19 @@
"weight": 5,
"volume": 1,
"bashing": 1
},
{
"type": "GENERIC",
"id": "craft",
"symbol": "%",
"color": "white",
"name": "in progress craft",
"description": "This is an in progress craft.",
"price": 0,
"weight": 1,
"volume": 1,
"max_charges": 20,
"use_action": "CRAFT",
"flags": [ "NO_SALVAGE", "TRADER_AVOID" ]
}
]
7 changes: 0 additions & 7 deletions data/json/player_activities.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,6 @@
"based_on": "neither",
"refuel_fires": true
},
{
"id": "ACT_LONGCRAFT",
"type": "activity_type",
"stop_phrase": "Stop crafting?",
"based_on": "neither",
"refuel_fires": true
},
{
"id": "ACT_DISASSEMBLE",
"type": "activity_type",
Expand Down
55 changes: 35 additions & 20 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "mtype.h"
#include "output.h"
#include "player.h"
#include "recipe.h"
#include "requirements.h"
#include "rng.h"
#include "skill.h"
Expand Down Expand Up @@ -57,7 +58,6 @@ const std::map< activity_id, std::function<void( player_activity *, player * )>
activity_handlers::do_turn_functions = {
{ activity_id( "ACT_BURROW" ), burrow_do_turn },
{ activity_id( "ACT_CRAFT" ), craft_do_turn },
{ activity_id( "ACT_LONGCRAFT" ), craft_do_turn },
{ activity_id( "ACT_FILL_LIQUID" ), fill_liquid_do_turn },
{ activity_id( "ACT_PICKAXE" ), pickaxe_do_turn },
{ activity_id( "ACT_DROP" ), drop_do_turn },
Expand Down Expand Up @@ -136,8 +136,6 @@ activity_handlers::finish_functions = {
{ activity_id( "ACT_WAIT_NPC" ), wait_npc_finish },
{ activity_id( "ACT_SOCIALIZE" ), socialize_finish },
{ activity_id( "ACT_TRY_SLEEP" ), try_sleep_finish },
{ activity_id( "ACT_CRAFT" ), craft_finish },
{ activity_id( "ACT_LONGCRAFT" ), longcraft_finish },
{ activity_id( "ACT_DISASSEMBLE" ), disassemble_finish },
{ activity_id( "ACT_BUILD" ), build_finish },
{ activity_id( "ACT_VIBE" ), vibe_finish },
Expand Down Expand Up @@ -2632,8 +2630,30 @@ void activity_handlers::try_sleep_finish( player_activity *act, player *p )

void activity_handlers::craft_do_turn( player_activity *act, player *p )
{
const recipe &rec = recipe_id( act->name ).obj();
item *craft = act->targets.front().get_item();

if( !craft->is_craft() ) {
debugmsg( "ACT_CRAFT target '%s' is not a craft. Aborting ACT_CRAFT.", craft->tname() );
p->cancel_activity();
return;
}
if( !p->has_item( *craft ) ) {
p->add_msg_player_or_npc(
string_format(
_( "You no longer have the %1$s in your possession. You stop crafting. Reactivate the %1$s to continue crafting." ),
craft->tname() ),
string_format(
_( "<npcname> no longer has the %s in their possession. <npcname> stops crafting." ),
craft->tname() )
);
p->cancel_activity();
return;
}

const recipe &rec = craft->get_making();
const float crafting_speed = p->crafting_speed_multiplier( rec, true );
const bool is_long = act->values[0];

if( crafting_speed <= 0.0f ) {
if( p->lighting_craft_speed_multiplier( rec ) <= 0.0f ) {
p->add_msg_if_player( m_bad, _( "You can no longer see well enough to keep crafting." ) );
Expand All @@ -2643,28 +2663,23 @@ void activity_handlers::craft_do_turn( player_activity *act, player *p )
p->cancel_activity();
return;
}
act->moves_left -= crafting_speed * p->get_moves();
p->set_moves( 0 );
if( calendar::once_every( 1_hours ) && crafting_speed < 0.75f ) {
// TODO: Describe the causes of slowdown
p->add_msg_if_player( m_bad, _( "You can't focus and are working slowly." ) );
}
}

void activity_handlers::craft_finish( player_activity *act, player *p )
{
p->complete_craft();
act->set_to_null();
}
craft->item_counter += crafting_speed * p->get_moves();
p->set_moves( 0 );

void activity_handlers::longcraft_finish( player_activity *act, player *p )
{
const int batch_size = act->values.front();
p->complete_craft();
act->set_to_null();
// Workaround for a bug where longcraft can be unset in complete_craft().
if( p->making_would_work( p->lastrecipe, batch_size ) ) {
p->last_craft->execute();
if( craft->item_counter >= rec.time ) {
p->cancel_activity();
item craft_copy = p->i_rem( craft );
p->complete_craft( craft_copy );
if( is_long ) {
if( p->making_would_work( p->lastrecipe, craft_copy.charges ) ) {
p->last_craft->execute();
}
}
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/activity_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,6 @@ void wait_weather_finish( player_activity *act, player *p );
void wait_npc_finish( player_activity *act, player *p );
void socialize_finish( player_activity *act, player *p );
void try_sleep_finish( player_activity *act, player *p );
void craft_finish( player_activity *act, player *p );
void longcraft_finish( player_activity *act, player *p );
void disassemble_finish( player_activity *act, player *p );
void build_finish( player_activity *act, player *p );
void vibe_finish( player_activity *act, player *p );
Expand Down
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
38 changes: 21 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,11 +420,15 @@ 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." ) );
}

if( food.is_craft() ) {
return ret_val<edible_rating>::make_failure( _( "That doesn't look edible in its current form." ) );
}

if( food.item_tags.count( "DIRTY" ) ) {
return ret_val<edible_rating>::make_failure(
_( "This is full of dirt after being on the ground." ) );
Expand Down Expand Up @@ -511,7 +515,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 +616,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 +754,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 +770,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 +878,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 +944,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
10 changes: 1 addition & 9 deletions src/craft_command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,7 @@ void craft_command::execute()
}
}

auto type = activity_id( is_long ? "ACT_LONGCRAFT" : "ACT_CRAFT" );
auto activity = player_activity( type, crafter->base_time_to_craft( *rec, batch_size ), -1, INT_MIN,
rec->ident().str() );
activity.values.push_back( batch_size );
activity.values.push_back( calendar::turn );
activity.coords.push_back( crafter->pos() );

crafter->assign_activity( activity );

crafter->start_craft( *rec, batch_size, is_long );
crafter->last_batch = batch_size;
crafter->lastrecipe = rec->ident();

Expand Down
5 changes: 4 additions & 1 deletion src/craft_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ class craft_command
private:
const recipe *rec = nullptr;
int batch_size = 0;
/** Indicates the activity_type for this crafting job, Either ACT_CRAFT or ACT_LONGCRAFT. */
/**
* Indicates whether the player has initiated a one off craft or wishes to craft as
* long as possible.
*/
bool is_long = false;
// This is mainly here for maintainability reasons.
player *crafter;
Expand Down
Loading

0 comments on commit 7225789

Please sign in to comment.