@@ -111,6 +111,7 @@ static const activity_id ACT_MEDITATE( "ACT_MEDITATE" );
111
111
static const activity_id ACT_MIGRATION_CANCEL ( " ACT_MIGRATION_CANCEL" );
112
112
static const activity_id ACT_MILK ( " ACT_MILK" );
113
113
static const activity_id ACT_MOVE_ITEMS ( " ACT_MOVE_ITEMS" );
114
+ static const activity_id ACT_MULTIPLE_CHOP_TREES ( " ACT_MULTIPLE_CHOP_TREES" );
114
115
static const activity_id ACT_OPEN_GATE ( " ACT_OPEN_GATE" );
115
116
static const activity_id ACT_OXYTORCH ( " ACT_OXYTORCH" );
116
117
static const activity_id ACT_PICKUP ( " ACT_PICKUP" );
@@ -161,11 +162,15 @@ static const item_group_id Item_spawn_data_grave( "grave" );
161
162
static const item_group_id Item_spawn_data_jewelry_front ( " jewelry_front" );
162
163
static const item_group_id Item_spawn_data_trash_forest ( " trash_forest" );
163
164
165
+ static const itype_id itype_2x4 ( " 2x4" );
164
166
static const itype_id itype_bone_human ( " bone_human" );
165
167
static const itype_id itype_disassembly ( " disassembly" );
166
168
static const itype_id itype_electrohack ( " electrohack" );
169
+ static const itype_id itype_log ( " log" );
167
170
static const itype_id itype_paper ( " paper" );
168
171
static const itype_id itype_pseudo_bio_picklock ( " pseudo_bio_picklock" );
172
+ static const itype_id itype_splinter ( " splinter" );
173
+ static const itype_id itype_stick_long ( " stick_long" );
169
174
170
175
static const json_character_flag json_flag_SUPER_HEARING ( " SUPER_HEARING" );
171
176
@@ -5392,6 +5397,235 @@ std::unique_ptr<activity_actor> pickup_menu_activity_actor::deserialize( JsonVal
5392
5397
return actor.clone ();
5393
5398
}
5394
5399
5400
+ static void chop_single_do_turn ( player_activity &act )
5401
+ {
5402
+ const map &here = get_map ();
5403
+ sfx::play_activity_sound ( " tool" , " axe" , sfx::get_heard_volume ( here.getlocal ( act.placement ) ) );
5404
+ if ( calendar::once_every ( 1_minutes ) ) {
5405
+ // ~ Sound of a wood chopping tool at work!
5406
+ sounds::sound ( here.getlocal ( act.placement ), 15 , sounds::sound_t ::activity, _ ( " CHK!" ) );
5407
+ }
5408
+ }
5409
+
5410
+ void chop_logs_activity_actor::start ( player_activity &act, Character & )
5411
+ {
5412
+ act.moves_total = moves;
5413
+ act.moves_left = moves;
5414
+ }
5415
+
5416
+ void chop_logs_activity_actor::do_turn ( player_activity &act, Character & )
5417
+ {
5418
+ chop_single_do_turn ( act );
5419
+ }
5420
+
5421
+ void chop_logs_activity_actor::finish ( player_activity &act, Character &who )
5422
+ {
5423
+ map &here = get_map ();
5424
+ const tripoint &pos = here.getlocal ( act.placement );
5425
+ int log_quan;
5426
+ int stick_quan;
5427
+ int splint_quan;
5428
+ if ( here.ter ( pos ) == t_trunk ) {
5429
+ log_quan = rng ( 2 , 3 );
5430
+ stick_quan = rng ( 0 , 1 );
5431
+ splint_quan = 0 ;
5432
+ } else if ( here.ter ( pos ) == t_stump ) {
5433
+ log_quan = rng ( 0 , 2 );
5434
+ stick_quan = 0 ;
5435
+ splint_quan = rng ( 5 , 15 );
5436
+ } else {
5437
+ log_quan = 0 ;
5438
+ stick_quan = 0 ;
5439
+ splint_quan = 0 ;
5440
+ }
5441
+ for ( int i = 0 ; i != log_quan; ++i ) {
5442
+ item obj ( itype_log, calendar::turn );
5443
+ obj.set_var ( " activity_var" , who.name );
5444
+ here.add_item_or_charges ( pos, obj );
5445
+ }
5446
+ for ( int i = 0 ; i != stick_quan; ++i ) {
5447
+ item obj ( itype_stick_long, calendar::turn );
5448
+ obj.set_var ( " activity_var" , who.name );
5449
+ here.add_item_or_charges ( pos, obj );
5450
+ }
5451
+ for ( int i = 0 ; i != splint_quan; ++i ) {
5452
+ item obj ( itype_splinter, calendar::turn );
5453
+ obj.set_var ( " activity_var" , who.name );
5454
+ here.add_item_or_charges ( pos, obj );
5455
+ }
5456
+ here.ter_set ( pos, t_dirt );
5457
+ who.add_msg_if_player ( m_good, _ ( " You finish chopping wood." ) );
5458
+
5459
+ act.set_to_null ();
5460
+ activity_handlers::resume_for_multi_activities ( who );
5461
+ }
5462
+
5463
+ void chop_logs_activity_actor::serialize ( JsonOut &jsout ) const
5464
+ {
5465
+ jsout.start_object ();
5466
+
5467
+ jsout.member ( " moves" , moves );
5468
+ jsout.member ( " tool" , tool );
5469
+
5470
+ jsout.end_object ();
5471
+ }
5472
+
5473
+ std::unique_ptr<activity_actor> chop_logs_activity_actor::deserialize ( JsonValue &jsin )
5474
+ {
5475
+ chop_logs_activity_actor actor ( {}, {} );
5476
+
5477
+ JsonObject data = jsin.get_object ();
5478
+
5479
+ data.read ( " moves" , actor.moves );
5480
+ data.read ( " tool" , actor.tool );
5481
+
5482
+ return actor.clone ();
5483
+ }
5484
+
5485
+ void chop_planks_activity_actor::start ( player_activity &act, Character & )
5486
+ {
5487
+ act.moves_total = moves;
5488
+ act.moves_left = moves;
5489
+ }
5490
+
5491
+ void chop_planks_activity_actor::do_turn ( player_activity &act, Character & )
5492
+ {
5493
+ chop_single_do_turn ( act );
5494
+ }
5495
+
5496
+ void chop_planks_activity_actor::finish ( player_activity &act, Character &who )
5497
+ {
5498
+ const int max_planks = 10 ;
5499
+ /* * @EFFECT_FABRICATION increases number of planks cut from a log */
5500
+ int planks = normal_roll ( 2 + who.get_skill_level ( skill_fabrication ), 1 );
5501
+ int wasted_planks = max_planks - planks;
5502
+ int scraps = rng ( wasted_planks, wasted_planks * 3 );
5503
+ planks = std::min ( planks, max_planks );
5504
+
5505
+ map &here = get_map ();
5506
+ if ( planks > 0 ) {
5507
+ here.spawn_item ( here.getlocal ( act.placement ), itype_2x4, planks, 0 , calendar::turn );
5508
+ who.add_msg_if_player ( m_good, n_gettext ( " You produce %d plank." , " You produce %d planks." ,
5509
+ planks ), planks );
5510
+ }
5511
+ if ( scraps > 0 ) {
5512
+ here.spawn_item ( here.getlocal ( act.placement ), itype_splinter, scraps, 0 , calendar::turn );
5513
+ who.add_msg_if_player ( m_good, n_gettext ( " You produce %d splinter." , " You produce %d splinters." ,
5514
+ scraps ), scraps );
5515
+ }
5516
+ if ( planks < max_planks / 2 ) {
5517
+ who.add_msg_if_player ( m_bad, _ ( " You waste a lot of the wood." ) );
5518
+ }
5519
+ act.set_to_null ();
5520
+ activity_handlers::resume_for_multi_activities ( who );
5521
+ }
5522
+
5523
+ void chop_planks_activity_actor::serialize ( JsonOut &jsout ) const
5524
+ {
5525
+ jsout.start_object ();
5526
+
5527
+ jsout.member ( " moves" , moves );
5528
+
5529
+ jsout.end_object ();
5530
+ }
5531
+
5532
+ std::unique_ptr<activity_actor> chop_planks_activity_actor::deserialize ( JsonValue &jsin )
5533
+ {
5534
+ chop_planks_activity_actor actor ( {} );
5535
+
5536
+ JsonObject data = jsin.get_object ();
5537
+
5538
+ data.read ( " moves" , actor.moves );
5539
+
5540
+ return actor.clone ();
5541
+ }
5542
+
5543
+ void chop_tree_activity_actor::start ( player_activity &act, Character & )
5544
+ {
5545
+ act.moves_total = moves;
5546
+ act.moves_left = moves;
5547
+ }
5548
+
5549
+ void chop_tree_activity_actor::do_turn ( player_activity &act, Character & )
5550
+ {
5551
+ chop_single_do_turn ( act );
5552
+ }
5553
+
5554
+ void chop_tree_activity_actor::finish ( player_activity &act, Character &who )
5555
+ {
5556
+ map &here = get_map ();
5557
+ const tripoint &pos = here.getlocal ( act.placement );
5558
+
5559
+ tripoint direction;
5560
+ if ( !who.is_npc () ) {
5561
+ if ( who.backlog .empty () || who.backlog .front ().id () != ACT_MULTIPLE_CHOP_TREES ) {
5562
+ while ( true ) {
5563
+ if ( const cata::optional<tripoint> dir = choose_direction (
5564
+ _ ( " Select a direction for the tree to fall in." ) ) ) {
5565
+ direction = *dir;
5566
+ break ;
5567
+ }
5568
+ // try again
5569
+ }
5570
+ }
5571
+ } else {
5572
+ creature_tracker &creatures = get_creature_tracker ();
5573
+ for ( const tripoint &elem : here.points_in_radius ( pos, 1 ) ) {
5574
+ bool cantuse = false ;
5575
+ tripoint direc = elem - pos;
5576
+ tripoint proposed_to = pos + point ( 3 * direction.x , 3 * direction.y );
5577
+ std::vector<tripoint> rough_tree_line = line_to ( pos, proposed_to );
5578
+ for ( const tripoint &elem : rough_tree_line ) {
5579
+ if ( creatures.creature_at ( elem ) ) {
5580
+ cantuse = true ;
5581
+ break ;
5582
+ }
5583
+ }
5584
+ if ( !cantuse ) {
5585
+ direction = direc;
5586
+ }
5587
+ }
5588
+ }
5589
+
5590
+ const tripoint to = pos + 3 * direction.xy () + point ( rng ( -1 , 1 ), rng ( -1 , 1 ) );
5591
+ std::vector<tripoint> tree = line_to ( pos, to, rng ( 1 , 8 ) );
5592
+ for ( const tripoint &elem : tree ) {
5593
+ here.batter ( elem, 300 , 5 );
5594
+ here.ter_set ( elem, t_trunk );
5595
+ }
5596
+
5597
+ here.ter_set ( pos, t_stump );
5598
+ who.add_msg_if_player ( m_good, _ ( " You finish chopping down a tree." ) );
5599
+ // sound of falling tree
5600
+ sfx::play_variant_sound ( " misc" , " timber" ,
5601
+ sfx::get_heard_volume ( here.getlocal ( act.placement ) ) );
5602
+ get_event_bus ().send <event_type::cuts_tree>( who.getID () );
5603
+ act.set_to_null ();
5604
+ activity_handlers::resume_for_multi_activities ( who );
5605
+ }
5606
+
5607
+ void chop_tree_activity_actor::serialize ( JsonOut &jsout ) const
5608
+ {
5609
+ jsout.start_object ();
5610
+
5611
+ jsout.member ( " moves" , moves );
5612
+ jsout.member ( " tool" , tool );
5613
+
5614
+ jsout.end_object ();
5615
+ }
5616
+
5617
+ std::unique_ptr<activity_actor> chop_tree_activity_actor::deserialize ( JsonValue &jsin )
5618
+ {
5619
+ chop_tree_activity_actor actor ( {}, {} );
5620
+
5621
+ JsonObject data = jsin.get_object ();
5622
+
5623
+ data.read ( " moves" , actor.moves );
5624
+ data.read ( " tool" , actor.tool );
5625
+
5626
+ return actor.clone ();
5627
+ }
5628
+
5395
5629
void firstaid_activity_actor::start ( player_activity &act, Character & )
5396
5630
{
5397
5631
act.moves_total = moves;
0 commit comments