diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index aceefd8d0a7a..af25204d183a 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -31,6 +31,7 @@ #include "construction_partial.h" #include "craft_command.h" #include "crafting.h" +#include "crafting_quality.h" #include "creature.h" #include "damage.h" #include "debug.h" @@ -113,6 +114,10 @@ static const activity_id ACT_CONSUME_FOOD_MENU( "ACT_CONSUME_FOOD_MENU" ); static const activity_id ACT_CONSUME_MEDS_MENU( "ACT_CONSUME_MEDS_MENU" ); static const activity_id ACT_CRACKING( "ACT_CRACKING" ); static const activity_id ACT_CRAFT( "ACT_CRAFT" ); +static constexpr auto craft_is_long_idx = 0; +static constexpr auto craft_bench_type_idx = 1; +static constexpr auto craft_tools_mult_percent_idx = 2; +static constexpr auto craft_tools_mult_next_refresh_idx = 3; static const activity_id ACT_DISMEMBER( "ACT_DISMEMBER" ); static const activity_id ACT_DISSECT( "ACT_DISSECT" ); static const activity_id ACT_EAT_MENU( "ACT_EAT_MENU" ); @@ -3800,18 +3805,28 @@ 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 bench_pos = act->coords.front(); // Ugly - bench_type bench_t = bench_type( act->values[1] ); - const float crafting_speed = crafting_speed_multiplier( *p, *craft, bench_location{bench_t, bench_pos} ); + bench_type bench_t = bench_type( act->values[craft_bench_type_idx] ); + + while( act->values.size() <= craft_tools_mult_next_refresh_idx ) { + act->values.push_back( 0 ); + } + + const auto now_turn = to_turn( calendar::turn ); + if( now_turn >= act->values[craft_tools_mult_next_refresh_idx] ) { + const auto tools_mult = crafting_tools_speed_multiplier( *p, rec ); + act->values[craft_tools_mult_percent_idx] = std::round( tools_mult * 100.0f ); + act->values[craft_tools_mult_next_refresh_idx] = INT_MAX; + } + + const auto tools_mult_cached = static_cast( act->values[craft_tools_mult_percent_idx] ) / + 100.0f; + const float crafting_speed = crafting_speed_multiplier( *p, *craft, bench_location{bench_t, bench_pos}, + tools_mult_cached ); const int assistants = p->available_assistant_count( craft->get_making() ); - const bool is_long = act->values[0]; + const bool is_long = act->values[craft_is_long_idx]; if( crafting_speed <= 0.0f ) { p->cancel_activity(); @@ -3838,30 +3853,15 @@ void activity_handlers::craft_do_turn( player_activity *act, player *p ) const auto new_counter_f = current_progress / base_total_moves * 10'000'000.0; // This is to ensure we don't over count skill steps const auto new_counter = std::min( static_cast( std::round( new_counter_f ) ), 10'000'000 ); + auto five_percent_steps = new_counter / 500'000 - old_counter / 500'000; craft->set_counter( new_counter ); p->set_moves( 0 ); - // Skill and tools are gained/consumed after every 5% progress - int five_percent_steps = craft->get_counter() / 500'000 - old_counter / 500'000; if( five_percent_steps > 0 ) { p->craft_skill_gain( *craft, five_percent_steps ); } - // Unlike skill, tools are consumed once at the start and should not be consumed at the end - if( craft->get_counter() >= 10'000'000 ) { - --five_percent_steps; - } - - if( five_percent_steps > 0 ) { - if( !p->craft_consume_tools( *craft, five_percent_steps, false ) ) { - // So we don't skip over any tool comsuption - craft->set_counter( craft->get_counter() - ( craft->get_counter() % 500'000 + 1 ) ); - p->cancel_activity(); - return; - } - } - // if item_counter has reached 100% or more if( craft->get_counter() >= 10'000'000 ) { //TODO!: CHEEKY check diff --git a/src/craft_command.cpp b/src/craft_command.cpp index 2b7db3227c27..5aadd24736e3 100644 --- a/src/craft_command.cpp +++ b/src/craft_command.cpp @@ -274,8 +274,65 @@ detached_ptr craft_command::create_in_progress_craft() new_craft->set_cached_tool_selections( tool_selections ); new_craft->set_tools_to_continue( true ); - // Pass true to indicate that we are starting the craft and the remainder should be consumed as well - crafter->craft_consume_tools( *new_craft, 1, true ); + + for( const comp_selection &tool_sel : tool_selections ) { + const auto type = tool_sel.comp.type; + if( tool_sel.comp.count > 0 ) { + const auto full_cost = tool_sel.comp.count * batch_size; + switch( tool_sel.use_from ) { + case usage_from::player: + if( !crafter->has_charges( type, full_cost ) ) { + return detached_ptr(); + } + break; + case usage_from::map: + if( !map_inv.has_charges( type, full_cost ) ) { + return detached_ptr(); + } + break; + case usage_from::both: + if( crafter->charges_of( type ) + map_inv.charges_of( type ) < full_cost ) { + return detached_ptr(); + } + break; + case usage_from::none: + case usage_from::cancel: + case usage_from::num_usages_from: + break; + } + } else { + switch( tool_sel.use_from ) { + case usage_from::player: + if( !crafter->has_amount( type, 1 ) ) { + return detached_ptr(); + } + break; + case usage_from::map: + if( !map_inv.has_tools( type, 1 ) ) { + return detached_ptr(); + } + break; + case usage_from::both: + if( crafter->amount_of( type ) + map_inv.amount_of( type ) < 1 ) { + return detached_ptr(); + } + break; + case usage_from::none: + case usage_from::cancel: + case usage_from::num_usages_from: + break; + } + } + } + for( const comp_selection &tool : tool_selections ) { + if( tool.comp.count <= 0 ) { + continue; + } + auto to_consume = tool; + to_consume.comp.count *= batch_size; + crafter->consume_tools( to_consume, 1 ); + } + new_craft->set_var( "craft_tools_fully_prepaid", 1 ); new_craft->set_next_failure_point( *crafter ); return new_craft; diff --git a/src/crafting.cpp b/src/crafting.cpp index 99ed1750f895..81e5d2bb407b 100644 --- a/src/crafting.cpp +++ b/src/crafting.cpp @@ -261,7 +261,8 @@ float crafting_speed_multiplier( const Character &who, const recipe &rec, bool ) } float crafting_speed_multiplier( const Character &who, const item &craft, - const bench_location &bench ) + const bench_location &bench, + const std::optional tools_multi_override ) { if( !craft.is_craft() ) { debugmsg( "Can't calculate crafting speed multiplier of non-craft '%s'", craft.tname() ); @@ -273,7 +274,9 @@ float crafting_speed_multiplier( const Character &who, const item &craft, const float light_multi = lighting_crafting_speed_multiplier( who, rec ); const float bench_multi = workbench_crafting_speed_multiplier( craft, bench ); const float morale_multi = morale_crafting_speed_multiplier( who, rec ); - const auto tools_multi = crafting_tools_speed_multiplier( who, rec ); + const auto tools_multi = tools_multi_override + ? *tools_multi_override + : crafting_tools_speed_multiplier( who, rec ); const float mutation_multi = who.mutation_value( "crafting_speed_modifier" ); const float game_opt_multi = get_option( "CRAFTING_SPEED_MULT" ) == 0 ? 9999 : 100.0f / get_option( "CRAFTING_SPEED_MULT" ); @@ -547,9 +550,9 @@ const inventory &Character::crafting_inventory( const tripoint &src_pos, int rad if( src_pos == tripoint_zero ) { inv_pos = pos(); } - if( cached_moves == moves - && cached_time == calendar::turn - && cached_position == inv_pos ) { + const auto cache_hit = cached_time == calendar::turn + && cached_position == inv_pos; + if( cache_hit ) { return cached_crafting_inventory; } cached_crafting_inventory.form_from_map( inv_pos, radius, this, false, clear_path ); @@ -753,6 +756,8 @@ item *Character::start_craft( craft_command &command, const tripoint & ) activity->values.push_back( command.is_long() ); // Ugly activity->values.push_back( static_cast( bench.type ) ); + activity->values.push_back( 100 ); + activity->values.push_back( 0 ); add_msg_player_or_npc( pgettext( "in progress craft", "You start working on the %s." ), diff --git a/src/crafting.h b/src/crafting.h index a64044c3f706..ecc961bc73da 100644 --- a/src/crafting.h +++ b/src/crafting.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -45,7 +46,8 @@ float morale_crafting_speed_multiplier( const Character &who, const recipe &rec float lighting_crafting_speed_multiplier( const Character &who, const recipe &rec ); float crafting_speed_multiplier( const Character &who, const recipe &rec, bool ); float crafting_speed_multiplier( const Character &who, const item &craft, - const bench_location &bench ); + const bench_location &bench, + std::optional tools_multi_override = std::nullopt ); void complete_craft( Character &who, item &craft ); namespace crafting diff --git a/src/iuse.cpp b/src/iuse.cpp index 7e812ab2f9ad..d53938439e13 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -8669,6 +8669,10 @@ int iuse::craft( player *p, item *it, bool, const tripoint &pos ) return 0; } + if( it->get_var( "craft_tools_fully_prepaid", 0 ) == 0 ) { + it->set_var( "craft_tools_fully_prepaid", 1 ); + } + bench_location best_bench = find_best_bench( *p, *it ); p->add_msg_player_or_npc( pgettext( "in progress craft", "You start working on the %s." ), @@ -8700,6 +8704,8 @@ int iuse::craft( player *p, item *it, bool, const tripoint &pos ) p->activity->values.push_back( 0 ); // Not a long craft // Ugly p->activity->values.push_back( static_cast( best_bench.type ) ); + p->activity->values.push_back( 100 ); + p->activity->values.push_back( 0 ); return 0; } diff --git a/src/player_activity.cpp b/src/player_activity.cpp index aab7e6ec6195..676105ca4cb9 100644 --- a/src/player_activity.cpp +++ b/src/player_activity.cpp @@ -53,6 +53,8 @@ static const activity_id ACT_CONSUME_DRINK_MENU( "ACT_CONSUME_DRINK_MENU" ); static const activity_id ACT_CONSUME_FOOD_MENU( "ACT_CONSUME_FOOD_MENU" ); static const activity_id ACT_CONSUME_MEDS_MENU( "ACT_CONSUME_MEDS_MENU" ); static const activity_id ACT_CRAFT( "ACT_CRAFT" ); +static constexpr auto craft_bench_type_idx = 1; +static constexpr auto craft_tools_mult_percent_idx = 2; static const activity_id ACT_DIG( "ACT_DIG" ); static const activity_id ACT_DIG_CHANNEL( "ACT_DIG_CHANNEL" ); static const activity_id ACT_EAT_MENU( "ACT_EAT_MENU" ); @@ -207,14 +209,16 @@ static std::string craft_progress_message( const avatar &u, const player_activit const recipe &rec = craft->get_making(); const tripoint bench_pos = act.coords.front(); // Ugly - bench_type bench_t = bench_type( act.values[1] ); + const auto bench_t = bench_type( act.values[craft_bench_type_idx] ); const bench_location bench{ bench_t, bench_pos }; const float light_mult = lighting_crafting_speed_multiplier( u, rec ); const float bench_mult = workbench_crafting_speed_multiplier( *craft, bench ); const float morale_mult = morale_crafting_speed_multiplier( u, rec ); - const auto tools_mult = crafting_tools_speed_multiplier( u, rec ); + const auto tools_mult = ( act.values.size() > craft_tools_mult_percent_idx ) + ? static_cast( act.values[craft_tools_mult_percent_idx] ) / 100.0f + : crafting_tools_speed_multiplier( u, rec ); const int assistants = u.available_assistant_count( craft->get_making() ); const float base_total_moves = std::max( 1, rec.batch_time( craft->charges, 1.0f, 0 ) ); const float assist_total_moves = std::max( 1, rec.batch_time( craft->charges, 1.0f, assistants ) );