Skip to content

Commit ce586ba

Browse files
fix: cache tool speed multiplier during crafting
Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> Assisted-by: openai/gpt-5.3-codex on opencode
1 parent 103f283 commit ce586ba

File tree

7 files changed

+111
-35
lines changed

7 files changed

+111
-35
lines changed

src/activity_handlers.cpp

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "construction_partial.h"
3232
#include "craft_command.h"
3333
#include "crafting.h"
34+
#include "crafting_quality.h"
3435
#include "creature.h"
3536
#include "damage.h"
3637
#include "debug.h"
@@ -113,6 +114,10 @@ static const activity_id ACT_CONSUME_FOOD_MENU( "ACT_CONSUME_FOOD_MENU" );
113114
static const activity_id ACT_CONSUME_MEDS_MENU( "ACT_CONSUME_MEDS_MENU" );
114115
static const activity_id ACT_CRACKING( "ACT_CRACKING" );
115116
static const activity_id ACT_CRAFT( "ACT_CRAFT" );
117+
static constexpr auto craft_is_long_idx = 0;
118+
static constexpr auto craft_bench_type_idx = 1;
119+
static constexpr auto craft_tools_mult_percent_idx = 2;
120+
static constexpr auto craft_tools_mult_next_refresh_idx = 3;
116121
static const activity_id ACT_DISMEMBER( "ACT_DISMEMBER" );
117122
static const activity_id ACT_DISSECT( "ACT_DISSECT" );
118123
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 )
38003805
return;
38013806
}
38023807

3803-
if( !p->can_continue_craft( *craft ) ) {
3804-
p->cancel_activity();
3805-
return;
3806-
}
3807-
38083808
const recipe &rec = craft->get_making();
38093809
const tripoint bench_pos = act->coords.front();
38103810
// Ugly
3811-
bench_type bench_t = bench_type( act->values[1] );
3812-
const float crafting_speed = crafting_speed_multiplier( *p, *craft, bench_location{bench_t, bench_pos} );
3811+
bench_type bench_t = bench_type( act->values[craft_bench_type_idx] );
3812+
3813+
while( act->values.size() <= craft_tools_mult_next_refresh_idx ) {
3814+
act->values.push_back( 0 );
3815+
}
3816+
3817+
const auto now_turn = to_turn<int>( calendar::turn );
3818+
if( now_turn >= act->values[craft_tools_mult_next_refresh_idx] ) {
3819+
const auto tools_mult = crafting_tools_speed_multiplier( *p, rec );
3820+
act->values[craft_tools_mult_percent_idx] = std::round( tools_mult * 100.0f );
3821+
act->values[craft_tools_mult_next_refresh_idx] = INT_MAX;
3822+
}
3823+
3824+
const auto tools_mult_cached = static_cast<float>( act->values[craft_tools_mult_percent_idx] ) /
3825+
100.0f;
3826+
const float crafting_speed = crafting_speed_multiplier( *p, *craft, bench_location{bench_t, bench_pos},
3827+
tools_mult_cached );
38133828
const int assistants = p->available_assistant_count( craft->get_making() );
3814-
const bool is_long = act->values[0];
3829+
const bool is_long = act->values[craft_is_long_idx];
38153830

38163831
if( crafting_speed <= 0.0f ) {
38173832
p->cancel_activity();
@@ -3838,30 +3853,15 @@ void activity_handlers::craft_do_turn( player_activity *act, player *p )
38383853
const auto new_counter_f = current_progress / base_total_moves * 10'000'000.0;
38393854
// This is to ensure we don't over count skill steps
38403855
const auto new_counter = std::min( static_cast<int>( std::round( new_counter_f ) ), 10'000'000 );
3856+
auto five_percent_steps = new_counter / 500'000 - old_counter / 500'000;
38413857
craft->set_counter( new_counter );
38423858

38433859
p->set_moves( 0 );
38443860

3845-
// Skill and tools are gained/consumed after every 5% progress
3846-
int five_percent_steps = craft->get_counter() / 500'000 - old_counter / 500'000;
38473861
if( five_percent_steps > 0 ) {
38483862
p->craft_skill_gain( *craft, five_percent_steps );
38493863
}
38503864

3851-
// Unlike skill, tools are consumed once at the start and should not be consumed at the end
3852-
if( craft->get_counter() >= 10'000'000 ) {
3853-
--five_percent_steps;
3854-
}
3855-
3856-
if( five_percent_steps > 0 ) {
3857-
if( !p->craft_consume_tools( *craft, five_percent_steps, false ) ) {
3858-
// So we don't skip over any tool comsuption
3859-
craft->set_counter( craft->get_counter() - ( craft->get_counter() % 500'000 + 1 ) );
3860-
p->cancel_activity();
3861-
return;
3862-
}
3863-
}
3864-
38653865
// if item_counter has reached 100% or more
38663866
if( craft->get_counter() >= 10'000'000 ) {
38673867
//TODO!: CHEEKY check

src/craft_command.cpp

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,65 @@ detached_ptr<item> craft_command::create_in_progress_craft()
274274

275275
new_craft->set_cached_tool_selections( tool_selections );
276276
new_craft->set_tools_to_continue( true );
277-
// Pass true to indicate that we are starting the craft and the remainder should be consumed as well
278-
crafter->craft_consume_tools( *new_craft, 1, true );
277+
278+
for( const comp_selection<tool_comp> &tool_sel : tool_selections ) {
279+
const auto type = tool_sel.comp.type;
280+
if( tool_sel.comp.count > 0 ) {
281+
const auto full_cost = tool_sel.comp.count * batch_size;
282+
switch( tool_sel.use_from ) {
283+
case usage_from::player:
284+
if( !crafter->has_charges( type, full_cost ) ) {
285+
return detached_ptr<item>();
286+
}
287+
break;
288+
case usage_from::map:
289+
if( !map_inv.has_charges( type, full_cost ) ) {
290+
return detached_ptr<item>();
291+
}
292+
break;
293+
case usage_from::both:
294+
if( crafter->charges_of( type ) + map_inv.charges_of( type ) < full_cost ) {
295+
return detached_ptr<item>();
296+
}
297+
break;
298+
case usage_from::none:
299+
case usage_from::cancel:
300+
case usage_from::num_usages_from:
301+
break;
302+
}
303+
} else {
304+
switch( tool_sel.use_from ) {
305+
case usage_from::player:
306+
if( !crafter->has_amount( type, 1 ) ) {
307+
return detached_ptr<item>();
308+
}
309+
break;
310+
case usage_from::map:
311+
if( !map_inv.has_tools( type, 1 ) ) {
312+
return detached_ptr<item>();
313+
}
314+
break;
315+
case usage_from::both:
316+
if( crafter->amount_of( type ) + map_inv.amount_of( type ) < 1 ) {
317+
return detached_ptr<item>();
318+
}
319+
break;
320+
case usage_from::none:
321+
case usage_from::cancel:
322+
case usage_from::num_usages_from:
323+
break;
324+
}
325+
}
326+
}
327+
for( const comp_selection<tool_comp> &tool : tool_selections ) {
328+
if( tool.comp.count <= 0 ) {
329+
continue;
330+
}
331+
auto to_consume = tool;
332+
to_consume.comp.count *= batch_size;
333+
crafter->consume_tools( to_consume, 1 );
334+
}
335+
new_craft->set_var( "craft_tools_fully_prepaid", 1 );
279336
new_craft->set_next_failure_point( *crafter );
280337

281338
return new_craft;

src/crafting.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ float crafting_speed_multiplier( const Character &who, const recipe &rec, bool )
261261
}
262262

263263
float crafting_speed_multiplier( const Character &who, const item &craft,
264-
const bench_location &bench )
264+
const bench_location &bench,
265+
const std::optional<float> tools_multi_override )
265266
{
266267
if( !craft.is_craft() ) {
267268
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,
273274
const float light_multi = lighting_crafting_speed_multiplier( who, rec );
274275
const float bench_multi = workbench_crafting_speed_multiplier( craft, bench );
275276
const float morale_multi = morale_crafting_speed_multiplier( who, rec );
276-
const auto tools_multi = crafting_tools_speed_multiplier( who, rec );
277+
const auto tools_multi = tools_multi_override.has_value()
278+
? *tools_multi_override
279+
: crafting_tools_speed_multiplier( who, rec );
277280
const float mutation_multi = who.mutation_value( "crafting_speed_modifier" );
278281
const float game_opt_multi = get_option<int>( "CRAFTING_SPEED_MULT" ) == 0 ? 9999 :
279282
100.0f / get_option<int>( "CRAFTING_SPEED_MULT" );
@@ -547,9 +550,9 @@ const inventory &Character::crafting_inventory( const tripoint &src_pos, int rad
547550
if( src_pos == tripoint_zero ) {
548551
inv_pos = pos();
549552
}
550-
if( cached_moves == moves
551-
&& cached_time == calendar::turn
552-
&& cached_position == inv_pos ) {
553+
const auto cache_hit = cached_time == calendar::turn
554+
&& cached_position == inv_pos;
555+
if( cache_hit ) {
553556
return cached_crafting_inventory;
554557
}
555558
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 & )
753756
activity->values.push_back( command.is_long() );
754757
// Ugly
755758
activity->values.push_back( static_cast<int>( bench.type ) );
759+
activity->values.push_back( 100 );
760+
activity->values.push_back( 0 );
756761

757762
add_msg_player_or_npc(
758763
pgettext( "in progress craft", "You start working on the %s." ),

src/crafting.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <list>
4+
#include <optional>
45
#include <set>
56
#include <vector>
67

@@ -45,7 +46,8 @@ float morale_crafting_speed_multiplier( const Character &who, const recipe &rec
4546
float lighting_crafting_speed_multiplier( const Character &who, const recipe &rec );
4647
float crafting_speed_multiplier( const Character &who, const recipe &rec, bool );
4748
float crafting_speed_multiplier( const Character &who, const item &craft,
48-
const bench_location &bench );
49+
const bench_location &bench,
50+
std::optional<float> tools_multi_override = std::nullopt );
4951
void complete_craft( Character &who, item &craft );
5052

5153
namespace crafting

src/crafting_quality.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ auto best_quality_multiplier_for_req( const inventory &crafting_inv,
1919
auto best_multiplier = 1.0f;
2020
const auto &quality = quality_req.type.obj();
2121
const auto per_level_multiplier = quality.crafting_speed_bonus_per_level;
22-
2322
crafting_inv.visit_items( [&]( const item * itm ) {
2423
const auto item_quality = itm->get_quality( quality_req.type );
2524
if( item_quality < quality_req.level ) {

src/iuse.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8669,6 +8669,10 @@ int iuse::craft( player *p, item *it, bool, const tripoint &pos )
86698669
return 0;
86708670
}
86718671

8672+
if( it->get_var( "craft_tools_fully_prepaid", 0 ) == 0 ) {
8673+
it->set_var( "craft_tools_fully_prepaid", 1 );
8674+
}
8675+
86728676
bench_location best_bench = find_best_bench( *p, *it );
86738677
p->add_msg_player_or_npc(
86748678
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 )
87008704
p->activity->values.push_back( 0 ); // Not a long craft
87018705
// Ugly
87028706
p->activity->values.push_back( static_cast<int>( best_bench.type ) );
8707+
p->activity->values.push_back( 100 );
8708+
p->activity->values.push_back( 0 );
87038709

87048710
return 0;
87058711
}

src/player_activity.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ static const activity_id ACT_CONSUME_DRINK_MENU( "ACT_CONSUME_DRINK_MENU" );
5353
static const activity_id ACT_CONSUME_FOOD_MENU( "ACT_CONSUME_FOOD_MENU" );
5454
static const activity_id ACT_CONSUME_MEDS_MENU( "ACT_CONSUME_MEDS_MENU" );
5555
static const activity_id ACT_CRAFT( "ACT_CRAFT" );
56+
static constexpr auto craft_bench_type_idx = 1;
57+
static constexpr auto craft_tools_mult_percent_idx = 2;
5658
static const activity_id ACT_DIG( "ACT_DIG" );
5759
static const activity_id ACT_DIG_CHANNEL( "ACT_DIG_CHANNEL" );
5860
static const activity_id ACT_EAT_MENU( "ACT_EAT_MENU" );
@@ -207,14 +209,19 @@ static std::string craft_progress_message( const avatar &u, const player_activit
207209
const recipe &rec = craft->get_making();
208210
const tripoint bench_pos = act.coords.front();
209211
// Ugly
210-
bench_type bench_t = bench_type( act.values[1] );
212+
bench_type bench_t = bench_type( act.values[craft_bench_type_idx] );
211213

212214
const bench_location bench{ bench_t, bench_pos };
213215

214216
const float light_mult = lighting_crafting_speed_multiplier( u, rec );
215217
const float bench_mult = workbench_crafting_speed_multiplier( *craft, bench );
216218
const float morale_mult = morale_crafting_speed_multiplier( u, rec );
217-
const auto tools_mult = crafting_tools_speed_multiplier( u, rec );
219+
auto tools_mult = 1.0f;
220+
if( act.values.size() > craft_tools_mult_percent_idx ) {
221+
tools_mult = static_cast<float>( act.values[craft_tools_mult_percent_idx] ) / 100.0f;
222+
} else {
223+
tools_mult = crafting_tools_speed_multiplier( u, rec );
224+
}
218225
const int assistants = u.available_assistant_count( craft->get_making() );
219226
const float base_total_moves = std::max( 1, rec.batch_time( craft->charges, 1.0f, 0 ) );
220227
const float assist_total_moves = std::max( 1, rec.batch_time( craft->charges, 1.0f, assistants ) );

0 commit comments

Comments
 (0)