diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index f55a035e1bf73..84afa89a49824 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -2716,6 +2716,11 @@ void activity_handlers::craft_do_turn( player_activity *act, player *p ) return; } + if( !p->can_continue_craft( *craft ) ) { + p->cancel_activity(); + return; + } + const recipe &rec = craft->get_making(); const tripoint loc = act->targets.front().where() == item_location::type::character ? tripoint_zero : act->targets.front().position(); diff --git a/src/crafting.cpp b/src/crafting.cpp index 4572372510154..70ade92e8ed45 100644 --- a/src/crafting.cpp +++ b/src/crafting.cpp @@ -821,6 +821,11 @@ void player::start_craft( craft_command &command, const tripoint &loc ) void player::complete_craft( item &craft, const tripoint &loc ) { + if( !craft.is_craft() ) { + debugmsg( "complete_craft() called on non-craft '%s.' Aborting.", craft.tname() ); + return; + } + const recipe &making = craft.get_making(); // Which recipe is it? const int batch_size = craft.charges; @@ -1085,6 +1090,27 @@ void player::complete_craft( item &craft, const tripoint &loc ) inv.restack( *this ); } +bool player::can_continue_craft( const item &craft ) +{ + if( !craft.is_craft() ) { + debugmsg( "complete_craft() called on non-craft '%s.' Aborting.", craft.tname() ); + return false; + } + + const recipe &rec = craft.get_making(); + if( has_recipe( &rec, crafting_inventory(), get_crafting_helpers() ) == -1 ) { + add_msg_player_or_npc( + string_format( _( "You don't know the recipe for the %s and can't continue crafting." ), + rec.result_name() ), + string_format( _( " doesn't know the recipe for the %s and can't continue crafting." ), + rec.result_name() ) + ); + return false; + } + + return true; +} + /* selection of component if a recipe requirement has multiple options (e.g. 'duct tap' or 'welder') */ comp_selection player::select_item_component( const std::vector &components, int batch, inventory &map_inv, bool can_cancel, diff --git a/src/iexamine.cpp b/src/iexamine.cpp index c0ab897dd834a..e968d96a114a7 100644 --- a/src/iexamine.cpp +++ b/src/iexamine.cpp @@ -4723,6 +4723,10 @@ void iexamine::workbench_internal( player &p, const tripoint &examp, const item *selected_craft = crafts[amenu2.ret].get_item(); + if( !p.can_continue_craft( *selected_craft ) ) { + break; + } + p.add_msg_player_or_npc( string_format( pgettext( "in progress craft", "You start working on the %s." ), selected_craft->tname() ), diff --git a/src/iuse.cpp b/src/iuse.cpp index 6ec5ad23cb7bf..d6924ed1f351b 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -8121,6 +8121,10 @@ int iuse::craft( player *p, item *it, bool, const tripoint & ) return 0; } + if( !p->can_continue_craft( p->weapon ) ) { + return 0; + } + p->add_msg_player_or_npc( string_format( pgettext( "in progress craft", "You start working on the %s." ), craft_name ), string_format( pgettext( "in progress craft", " starts working on the %s." ), diff --git a/src/player.h b/src/player.h index d2bf33f652d7e..28ae409693be7 100644 --- a/src/player.h +++ b/src/player.h @@ -1443,6 +1443,13 @@ class player : public Character /** consume components and create an active, in progress craft containing them */ void start_craft( craft_command &command, const tripoint &loc ); void complete_craft( item &craft, const tripoint &loc = tripoint_zero ); + /** + * Check if the player meets the requirements to continue the in progress craft and if + * unable to continue print messages explaining the reason. + * @param craft the currently in progress craft + * @return if the craft can be continued + */ + bool can_continue_craft( const item &craft ); /** Returns nearby NPCs ready and willing to help with crafting. */ std::vector get_crafting_helpers() const; int get_num_crafting_helpers( int max ) const;