Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consume tool charges incrementally during crafting #31844

Merged
merged 3 commits into from
Jun 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3024,7 +3024,7 @@ void activity_handlers::craft_do_turn( player_activity *act, player *p )
}

// item_counter represents the percent progress relative to the base batch time
// stored precise to 5 decimal places ( e.g. 67.32 percent would be stored as 6732000 )
// stored precise to 5 decimal places ( e.g. 67.32 percent would be stored as 6'732'000 )
const int old_counter = craft->item_counter;

// Base moves for batch size with no speed modifier or assistants
Expand All @@ -3036,23 +3036,37 @@ void activity_handlers::craft_do_turn( player_activity *act, player *p )
// Delta progress in moves adjusted for current crafting speed
const double delta_progress = p->get_moves() * base_total_moves / cur_total_moves;
// Current progress in moves
const double current_progress = craft->item_counter * base_total_moves / 10000000.0 +
const double current_progress = craft->item_counter * base_total_moves / 10'000'000.0 +
delta_progress;
// Current progress as a percent of base_total_moves to 2 decimal places
craft->item_counter = round( current_progress / base_total_moves * 10000000.0 );
craft->item_counter = round( current_progress / base_total_moves * 10'000'000.0 );
p->set_moves( 0 );

// This is to ensure we don't over count skill steps
craft->item_counter = std::min( craft->item_counter, 10000000 );
craft->item_counter = std::min( craft->item_counter, 10'000'000 );

// Skill and tools are gained/consumed after every 5% progress
int five_percent_steps = craft->item_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->item_counter >= 10'000'000 ) {
--five_percent_steps;
}

// Skill is gained after every 5% progress
const int skill_steps = craft->item_counter / 500000 - old_counter / 500000;
if( skill_steps > 0 ) {
p->craft_skill_gain( *craft, skill_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->item_counter -= craft->item_counter % 500'000 + 1;
p->cancel_activity();
return;
}
}

// if item_counter has reached 100% or more
if( craft->item_counter >= 10000000 ) {
if( craft->item_counter >= 10'000'000 ) {
item craft_copy = *craft;
act->targets.front().remove_item();
p->cancel_activity();
Expand Down
96 changes: 90 additions & 6 deletions src/craft_command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include "debug.h"
#include "game_constants.h"
#include "inventory.h"
#include "io.h"
#include "item.h"
#include "json.h"
#include "output.h"
#include "player.h"
#include "recipe.h"
Expand All @@ -35,6 +37,70 @@ std::string comp_selection<CompType>::nname() const
return item::nname( comp.type, comp.count );
}

namespace io
{

static const std::map<std::string, usage> usage_map = {{
{ "map", usage::use_from_map },
{ "player", usage::use_from_player },
{ "both", usage::use_from_both },
{ "none", usage::use_from_none },
{ "cancel", usage::cancel }
}
};

template<>
usage string_to_enum<usage>( const std::string &data )
{
return string_to_enum_look_up( usage_map, data );
}

template<>
const std::string enum_to_string<usage>( usage data )
{
const auto iter = std::find_if( usage_map.begin(), usage_map.end(),
[data]( const std::pair<std::string, usage> &kv ) {
return kv.second == data;
} );

if( iter == usage_map.end() ) {
throw InvalidEnumString{};
}

return iter->first;
}

} // namespace io

template<typename CompType>
void comp_selection<CompType>::serialize( JsonOut &jsout ) const
{
jsout.start_object();

jsout.member( "use_from", io::enum_to_string( use_from ) );
jsout.member( "type", comp.type );
jsout.member( "count", comp.count );

jsout.end_object();
}

template<typename CompType>
void comp_selection<CompType>::deserialize( JsonIn &jsin )
{
JsonObject data = jsin.get_object();

std::string use_from_str;
data.read( "use_from", use_from_str );
use_from = io::string_to_enum<usage>( use_from_str );
data.read( "type", comp.type );
data.read( "count", comp.count );
}

template void comp_selection<tool_comp>::serialize( JsonOut &jsout ) const;
template void comp_selection<item_comp>::serialize( JsonOut &jsout ) const;
template void comp_selection<tool_comp>::deserialize( JsonIn &jsin );
template void comp_selection<item_comp>::deserialize( JsonIn &jsin );

void craft_command::execute( const tripoint &new_loc )
{
if( empty() ) {
Expand Down Expand Up @@ -62,6 +128,18 @@ void craft_command::execute( const tripoint &new_loc )
}

if( need_selections ) {
if( !crafter->can_make( rec, batch_size ) ) {
if( crafter->can_start_craft( rec, batch_size ) ) {
if( !query_yn( _( "You don't have enough charges to complete the %s.\n"
"Start crafting anyway?" ), rec->result_name() ) ) {
return;
}
} else {
debugmsg( "Tried to start craft without sufficient charges" );
return;
}
}

item_selections.clear();
const auto needs = rec->requirements();
const auto filter = rec->get_component_filter();
Expand All @@ -78,7 +156,9 @@ void craft_command::execute( const tripoint &new_loc )
tool_selections.clear();
for( const auto &it : needs.get_tools() ) {
comp_selection<tool_comp> ts = crafter->select_tool_component(
it, batch_size, map_inv, DEFAULT_HOTKEYS, true );
it, batch_size, map_inv, DEFAULT_HOTKEYS, true, true, []( int charges ) {
return charges / 20 + charges % 20;
} );
if( ts.use_from == cancel ) {
return;
}
Expand Down Expand Up @@ -162,17 +242,21 @@ item craft_command::create_in_progress_craft()
used.splice( used.end(), tmp );
}

for( const auto &it : tool_selections ) {
crafter->consume_tools( it, batch_size );
}

for( const comp_selection<item_comp> &selection : item_selections ) {
item_comp comp_used = selection.comp;
comp_used.count *= batch_size;
comps_used.emplace_back( comp_used );
}

return item( rec, batch_size, used, comps_used );
item new_craft( rec, batch_size, used, comps_used );

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 );
new_craft.set_next_failure_point( *crafter );

return new_craft;
}

std::vector<comp_selection<item_comp>> craft_command::check_item_components_missing(
Expand Down
3 changes: 3 additions & 0 deletions src/craft_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ struct comp_selection {

/** provides a translated name for 'comp', suffixed with it's location e.g '(nearby)'. */
std::string nname() const;

void serialize( JsonOut &jsout ) const;
void deserialize( JsonIn &jsin );
};

/**
Expand Down
Loading