@@ -1267,22 +1267,7 @@ void hacksaw_activity_actor::start( player_activity &act, Character &/*who*/ )
12671267 return ;
12681268 }
12691269
1270- int qual = 0 ;
1271- if ( type.has_value () ) {
1272- item veh_tool = item ( type.value (), calendar::turn );
1273- for ( const std::pair<const quality_id, int > &quality : type.value ()->qualities ) {
1274- if ( quality.first == qual_SAW_M ) {
1275- qual = quality.second ;
1276- }
1277- }
1278- for ( const std::pair<const quality_id, int > &quality : type.value ()->charged_qualities ) {
1279- if ( quality.first == qual_SAW_M ) {
1280- qual = std::max ( qual, quality.second );
1281- }
1282- }
1283- } else {
1284- qual = tool->get_quality ( qual_SAW_M );
1285- }
1270+ int qual = get_tool_quality ();
12861271 if ( qual < 2 ) {
12871272 if ( !testing ) {
12881273 debugmsg ( " Item %s with 'HACKSAW' use action requires SAW_M quality of at least 2." ,
@@ -1298,6 +1283,7 @@ void hacksaw_activity_actor::start( player_activity &act, Character &/*who*/ )
12981283 act.moves_total = moves_before_quality / ( qual - 1 );
12991284 add_msg_debug ( debugmode::DF_ACTIVITY, " %s moves_total: %d" , act.id ().str (), act.moves_total );
13001285 act.moves_left = act.moves_total ;
1286+ moves_left = act.moves_left ;
13011287}
13021288
13031289static void tool_out_of_charges ( Character &who, const std::string &tool_name )
@@ -1311,8 +1297,9 @@ static void tool_out_of_charges( Character &who, const std::string &tool_name )
13111297 who.cancel_activity ();
13121298}
13131299
1314- void hacksaw_activity_actor::do_turn ( player_activity &/* act*/ , Character &who )
1300+ void hacksaw_activity_actor::do_turn ( player_activity &act, Character &who )
13151301{
1302+ moves_left = act.moves_left ;
13161303 map &here = get_map ();
13171304
13181305 std::string method = " HACKSAW" ;
@@ -1428,18 +1415,58 @@ void hacksaw_activity_actor::finish( player_activity &act, Character &who )
14281415 act.set_to_null ();
14291416}
14301417
1431- // TODO: Make hacksawing resumable with different tools with the same SAW_M quality.
1432- // Potentially make it possible to resume with different SAW_M quality and recalculate time to completion partway through.
1433- // This is really not a big deal, and will cost a few minutes of in game time and part of a medium battery charge at worst as someone accidentally cancels the activity_actor and has to start again
1434- // If a few minutes are life and death, sawing metal may not be the wise choice in the first place.
1435- bool hacksaw_activity_actor::can_resume_with_internal ( const activity_actor &other,
1436- const Character &/* who*/ ) const
1418+ float hacksaw_activity_actor::exertion_level () const
14371419{
1438- const hacksaw_activity_actor &actor = static_cast <const hacksaw_activity_actor &>
1439- ( other );
1440- return actor.target == target && ( ( veh_pos.has_value () &&
1441- veh_pos.value () == actor.veh_pos .value_or ( tripoint_bub_ms::max ) ) ||
1442- actor.tool .operator == ( tool ) );
1420+ if ( tool->ammo_required () ) {
1421+ return LIGHT_EXERCISE;
1422+ } else {
1423+ return get_type ()->exertion_level ();
1424+ }
1425+ }
1426+
1427+ int hacksaw_activity_actor::get_tool_quality () const
1428+ {
1429+ int qual = 0 ;
1430+ if ( type.has_value () ) {
1431+ item veh_tool = item ( type.value (), calendar::turn );
1432+ for ( const std::pair<const quality_id, int > &quality : type.value ()->qualities ) {
1433+ if ( quality.first == qual_SAW_M ) {
1434+ qual = quality.second ;
1435+ }
1436+ }
1437+ for ( const std::pair<const quality_id, int > &quality : type.value ()->charged_qualities ) {
1438+ if ( quality.first == qual_SAW_M ) {
1439+ qual = std::max ( qual, quality.second );
1440+ }
1441+ }
1442+ } else {
1443+ qual = tool->get_quality ( qual_SAW_M );
1444+ }
1445+
1446+ return qual;
1447+ }
1448+
1449+ void hacksaw_activity_actor::set_resume_values_internal ( const activity_actor &other,
1450+ const Character &/* who*/ )
1451+ {
1452+ // This method recalculates moves_left based on tool quality comparison but it doesn't have
1453+ // access to update the moves_left on the corresponding player_activity. You must set the
1454+ // player_activity's moves_left separately after resuming the activity_actor.
1455+
1456+ const hacksaw_activity_actor &actor = static_cast <const hacksaw_activity_actor &>( other );
1457+
1458+ int actor_qual = actor.get_tool_quality ();
1459+ int qual = get_tool_quality ();
1460+
1461+ int new_moves_left = -1 ;
1462+ if ( actor_qual > 1 ) {
1463+ new_moves_left = moves_left * ( qual - 1 ) / ( actor_qual - 1 );
1464+ }
1465+ add_msg_debug ( debugmode::DF_ACTIVITY,
1466+ " Hacksaw resume. Actor quality: %d, quality: %d, moves_left: %d, new_moves_left: %d." ,
1467+ actor_qual, qual, moves_left, new_moves_left );
1468+ moves_left = new_moves_left;
1469+ tool = actor.tool ;
14431470}
14441471
14451472void hacksaw_activity_actor::serialize ( JsonOut &jsout ) const
@@ -1449,6 +1476,7 @@ void hacksaw_activity_actor::serialize( JsonOut &jsout ) const
14491476 jsout.member ( " tool" , tool );
14501477 jsout.member ( " type" , type );
14511478 jsout.member ( " veh_pos" , veh_pos );
1479+ jsout.member ( " moves_left" , moves_left );
14521480 jsout.end_object ();
14531481}
14541482
@@ -1460,6 +1488,7 @@ std::unique_ptr<activity_actor> hacksaw_activity_actor::deserialize( JsonValue &
14601488 data.read ( " tool" , actor.tool );
14611489 data.read ( " type" , actor.type );
14621490 data.read ( " veh_pos" , actor.veh_pos );
1491+ data.read ( " moves_left" , actor.moves_left );
14631492 return actor.clone ();
14641493}
14651494
0 commit comments