diff --git a/data/json/npcs/TALK_COMMON_ALLY.json b/data/json/npcs/TALK_COMMON_ALLY.json index 6346cca2ff240..0d81881186451 100644 --- a/data/json/npcs/TALK_COMMON_ALLY.json +++ b/data/json/npcs/TALK_COMMON_ALLY.json @@ -815,6 +815,12 @@ "condition": { "not": "npc_has_activity" }, "effect": "do_construction" }, + { + "text": "Please do any mining work that you can.", + "topic": "TALK_DONE", + "condition": { "not": "npc_has_activity" }, + "effect": "do_mining" + }, { "text": "Please study from a book.", "topic": "TALK_DONE", diff --git a/data/json/player_activities.json b/data/json/player_activities.json index 79e7bdaaa437e..ae1f0ce274712 100644 --- a/data/json/player_activities.json +++ b/data/json/player_activities.json @@ -35,6 +35,16 @@ "no_resume": true, "multi_activity": true }, + { + "id": "ACT_MULTIPLE_MINE", + "type": "activity_type", + "activity_level": "EXTRA_EXERCISE", + "verb": "mining", + "based_on": "neither", + "suspendable": false, + "no_resume": true, + "multi_activity": true + }, { "id": "ACT_TIDY_UP", "type": "activity_type", diff --git a/data/json/requirements/toolsets.json b/data/json/requirements/toolsets.json index d8e0aa03fed47..46bff49f41fc1 100644 --- a/data/json/requirements/toolsets.json +++ b/data/json/requirements/toolsets.json @@ -110,6 +110,12 @@ ] ] }, + { + "id": "mining_standard", + "type": "requirement", + "//": "mining", + "tools": [ [ [ "pickaxe", -1 ], [ "jackhammer", 10 ], [ "elec_jackhammer", 3500 ] ] ] + }, { "id": "bronzesmithing_tools", "type": "requirement", diff --git a/src/activity_handlers.cpp b/src/activity_handlers.cpp index 5e96d8a3640d7..6c7645441acaf 100644 --- a/src/activity_handlers.cpp +++ b/src/activity_handlers.cpp @@ -158,6 +158,7 @@ static const activity_id ACT_MULTIPLE_BUTCHER( "ACT_MULTIPLE_BUTCHER" ); static const activity_id ACT_MULTIPLE_CHOP_PLANKS( "ACT_MULTIPLE_CHOP_PLANKS" ); static const activity_id ACT_MULTIPLE_CHOP_TREES( "ACT_MULTIPLE_CHOP_TREES" ); static const activity_id ACT_MULTIPLE_CONSTRUCTION( "ACT_MULTIPLE_CONSTRUCTION" ); +static const activity_id ACT_MULTIPLE_MINE( "ACT_MULTIPLE_MINE" ); static const activity_id ACT_MULTIPLE_FARM( "ACT_MULTIPLE_FARM" ); static const activity_id ACT_MULTIPLE_FISH( "ACT_MULTIPLE_FISH" ); static const activity_id ACT_OPEN_GATE( "ACT_OPEN_GATE" ); @@ -293,6 +294,7 @@ activity_handlers::do_turn_functions = { { ACT_WEAR, wear_do_turn }, { ACT_MULTIPLE_FISH, multiple_fish_do_turn }, { ACT_MULTIPLE_CONSTRUCTION, multiple_construction_do_turn }, + { ACT_MULTIPLE_MINE, multiple_mine_do_turn }, { ACT_MULTIPLE_BUTCHER, multiple_butcher_do_turn }, { ACT_MULTIPLE_FARM, multiple_farm_do_turn }, { ACT_FETCH_REQUIRED, fetch_do_turn }, @@ -1939,7 +1941,7 @@ void activity_handlers::make_zlave_finish( player_activity *act, player *p ) void activity_handlers::pickaxe_do_turn( player_activity *act, player * ) { - const tripoint &pos = act->placement; + const tripoint &pos = g->m.getlocal( act->placement ); sfx::play_activity_sound( "tool", "pickaxe", sfx::get_heard_volume( pos ) ); // each turn is too much if( calendar::once_every( 1_minutes ) ) { @@ -1950,37 +1952,46 @@ void activity_handlers::pickaxe_do_turn( player_activity *act, player * ) void activity_handlers::pickaxe_finish( player_activity *act, player *p ) { - const tripoint pos( act->placement ); + const tripoint pos( g->m.getlocal( act->placement ) ); item &it = p->i_at( act->position ); // Invalidate the activity early to prevent a query from mod_pain() act->set_to_null(); - const int helpersize = g->u.get_num_crafting_helpers( 3 ); - if( g->m.is_bashable( pos ) && g->m.has_flag( flag_SUPPORTS_ROOF, pos ) && - g->m.ter( pos ) != t_tree ) { - // Tunneling through solid rock is hungry, sweaty, tiring, backbreaking work - // Betcha wish you'd opted for the J-Hammer ;P - p->mod_stored_nutr( 15 - ( helpersize * 3 ) ); - p->mod_thirst( 15 - ( helpersize * 3 ) ); - if( p->has_trait( trait_STOCKY_TROGLO ) ) { - // Yep, dwarves can dig longer before tiring - p->mod_fatigue( 20 - ( helpersize * 3 ) ); - } else { - p->mod_fatigue( 30 - ( helpersize * 3 ) ); - } - p->mod_pain( std::max( 0, ( 2 * static_cast( rng( 1, 3 ) ) ) - helpersize ) ); - } else if( g->m.move_cost( pos ) == 2 && g->get_levz() == 0 && - g->m.ter( pos ) != t_dirt && g->m.ter( pos ) != t_grass ) { - //Breaking up concrete on the surface? not nearly as bad - p->mod_stored_nutr( 5 - ( helpersize ) ); - p->mod_thirst( 5 - ( helpersize ) ); - p->mod_fatigue( 10 - ( helpersize * 2 ) ); - } - p->add_msg_if_player( m_good, _( "You finish digging." ) ); + if( p->is_avatar() ) { + const int helpersize = g->u.get_num_crafting_helpers( 3 ); + if( g->m.is_bashable( pos ) && g->m.has_flag( flag_SUPPORTS_ROOF, pos ) && + g->m.ter( pos ) != t_tree ) { + // Tunneling through solid rock is hungry, sweaty, tiring, backbreaking work + // Betcha wish you'd opted for the J-Hammer ;P + p->mod_stored_nutr( 15 - ( helpersize * 3 ) ); + p->mod_thirst( 15 - ( helpersize * 3 ) ); + if( p->has_trait( trait_STOCKY_TROGLO ) ) { + // Yep, dwarves can dig longer before tiring + p->mod_fatigue( 20 - ( helpersize * 3 ) ); + } else { + p->mod_fatigue( 30 - ( helpersize * 3 ) ); + } + p->mod_pain( std::max( 0, ( 2 * static_cast( rng( 1, 3 ) ) ) - helpersize ) ); + } else if( g->m.move_cost( pos ) == 2 && g->get_levz() == 0 && + g->m.ter( pos ) != t_dirt && g->m.ter( pos ) != t_grass ) { + //Breaking up concrete on the surface? not nearly as bad + p->mod_stored_nutr( 5 - ( helpersize ) ); + p->mod_thirst( 5 - ( helpersize ) ); + p->mod_fatigue( 10 - ( helpersize * 2 ) ); + } + } + p->add_msg_player_or_npc( m_good, + _( "You finish digging." ), + _( " finishes digging." ) ); g->m.destroy( pos, true ); it.charges = std::max( 0, it.charges - it.type->charges_to_use() ); if( it.charges == 0 && it.destroyed_at_zero_charges() ) { p->i_rem( &it ); } + if( resume_for_multi_activities( *p ) ) { + for( item &elem : g->m.i_at( pos ) ) { + elem.set_var( "activity_var", p->name ); + } + } } void activity_handlers::pulp_do_turn( player_activity *act, player *p ) @@ -3683,6 +3694,12 @@ void activity_handlers::multiple_construction_do_turn( player_activity *act, pla generic_multi_activity_handler( *act, *p ); } +void activity_handlers::multiple_mine_do_turn( player_activity *act, player *p ) +{ + generic_multi_activity_handler( *act, *p ); +} + + void activity_handlers::multiple_chop_planks_do_turn( player_activity *act, player *p ) { generic_multi_activity_handler( *act, *p ); @@ -4108,26 +4125,36 @@ void activity_handlers::chop_planks_finish( player_activity *act, player *p ) void activity_handlers::jackhammer_do_turn( player_activity *act, player * ) { - sfx::play_activity_sound( "tool", "jackhammer", sfx::get_heard_volume( act->placement ) ); + sfx::play_activity_sound( "tool", "jackhammer", + sfx::get_heard_volume( g->m.getlocal( act->placement ) ) ); if( calendar::once_every( 1_minutes ) ) { - //~ Sound of a jackhammer at work! - sounds::sound( act->placement, 15, sounds::sound_t::destructive_activity, _( "TATATATATATATAT!" ) ); + sounds::sound( g->m.getlocal( act->placement ), 15, sounds::sound_t::destructive_activity, + //~ Sound of a jackhammer at work! + _( "TATATATATATATAT!" ) ); } } void activity_handlers::jackhammer_finish( player_activity *act, player *p ) { - const tripoint &pos = act->placement; + const tripoint &pos = g->m.getlocal( act->placement ); g->m.destroy( pos, true ); - const int helpersize = g->u.get_num_crafting_helpers( 3 ); - p->mod_stored_nutr( 5 - helpersize ); - p->mod_thirst( 5 - helpersize ); - p->mod_fatigue( 10 - ( helpersize * 2 ) ); - p->add_msg_if_player( m_good, _( "You finish drilling." ) ); - + if( p->is_avatar() ) { + const int helpersize = g->u.get_num_crafting_helpers( 3 ); + p->mod_stored_nutr( 5 - helpersize ); + p->mod_thirst( 5 - helpersize ); + p->mod_fatigue( 10 - ( helpersize * 2 ) ); + } + p->add_msg_player_or_npc( m_good, + _( "You finish drilling." ), + _( " finishes drilling." ) ); act->set_to_null(); + if( resume_for_multi_activities( *p ) ) { + for( item &elem : g->m.i_at( pos ) ) { + elem.set_var( "activity_var", p->name ); + } + } } void activity_handlers::dig_do_turn( player_activity *act, player * ) diff --git a/src/activity_handlers.h b/src/activity_handlers.h index 36dad46c44a2a..9e7677752a71a 100644 --- a/src/activity_handlers.h +++ b/src/activity_handlers.h @@ -58,6 +58,7 @@ enum do_activity_reason : int { ALREADY_WORKING, // somebody is already working there NEEDS_VEH_DECONST, // There is a vehicle part there that we can deconstruct, given the right tools. NEEDS_VEH_REPAIR, // There is a vehicle part there that can be repaired, given the right tools. + NEEDS_MINING, // This spot can be mined, if the right tool is present. NEEDS_FISHING // This spot can be fished, if the right tool is present. }; @@ -161,6 +162,7 @@ void move_items_do_turn( player_activity *act, player *p ); void multiple_farm_do_turn( player_activity *act, player *p ); void multiple_fish_do_turn( player_activity *act, player *p ); void multiple_construction_do_turn( player_activity *act, player *p ); +void multiple_mine_do_turn( player_activity *act, player *p ); void multiple_butcher_do_turn( player_activity *act, player *p ); void vehicle_deconstruction_do_turn( player_activity *act, player *p ); void vehicle_repair_do_turn( player_activity *act, player *p ); diff --git a/src/activity_item_handling.cpp b/src/activity_item_handling.cpp index cc293142b27e3..68ce5fbe27b58 100644 --- a/src/activity_item_handling.cpp +++ b/src/activity_item_handling.cpp @@ -58,6 +58,7 @@ static const activity_id ACT_CHOP_TREE( "ACT_CHOP_TREE" ); static const activity_id ACT_CHURN( "ACT_CHURN" ); static const activity_id ACT_FETCH_REQUIRED( "ACT_FETCH_REQUIRED" ); static const activity_id ACT_FISH( "ACT_FISH" ); +static const activity_id ACT_JACKHAMMER( "ACT_JACKHAMMER" ); static const activity_id ACT_MOVE_LOOT( "ACT_MOVE_LOOT" ); static const activity_id ACT_MULTIPLE_BUTCHER( "ACT_MULTIPLE_BUTCHER" ); static const activity_id ACT_MULTIPLE_CHOP_PLANKS( "ACT_MULTIPLE_CHOP_PLANKS" ); @@ -65,6 +66,8 @@ static const activity_id ACT_MULTIPLE_CHOP_TREES( "ACT_MULTIPLE_CHOP_TREES" ); static const activity_id ACT_MULTIPLE_CONSTRUCTION( "ACT_MULTIPLE_CONSTRUCTION" ); static const activity_id ACT_MULTIPLE_FARM( "ACT_MULTIPLE_FARM" ); static const activity_id ACT_MULTIPLE_FISH( "ACT_MULTIPLE_FISH" ); +static const activity_id ACT_MULTIPLE_MINE( "ACT_MULTIPLE_MINE" ); +static const activity_id ACT_PICKAXE( "ACT_PICKAXE" ); static const activity_id ACT_TIDY_UP( "ACT_TIDY_UP" ); static const activity_id ACT_VEHICLE( "ACT_VEHICLE" ); static const activity_id ACT_VEHICLE_DECONSTRUCTION( "ACT_VEHICLE_DECONSTRUCTION" ); @@ -83,6 +86,7 @@ static const zone_type_id zone_type_FARM_PLOT( "FARM_PLOT" ); static const zone_type_id zone_type_FISHING_SPOT( "FISHING_SPOT" ); static const zone_type_id zone_type_LOOT_CORPSE( "LOOT_CORPSE" ); static const zone_type_id zone_type_LOOT_IGNORE( "LOOT_IGNORE" ); +static const zone_type_id zone_type_MINING( "MINING" ); static const zone_type_id zone_type_LOOT_UNSORTED( "LOOT_UNSORTED" ); static const zone_type_id zone_type_LOOT_WOOD( "LOOT_WOOD" ); static const zone_type_id zone_type_VEHICLE_DECONSTRUCT( "VEHICLE_DECONSTRUCT" ); @@ -97,6 +101,7 @@ static const quality_id qual_SAW_W( "SAW_W" ); static const quality_id qual_WELD( "WELD" ); static const std::string flag_BUTCHER_EQ( "BUTCHER_EQ" ); +static const std::string flag_DIG_TOOL( "DIG_TOOL" ); static const std::string flag_FISHABLE( "FISHABLE" ); static const std::string flag_FISH_GOOD( "FISH_GOOD" ); static const std::string flag_FISH_POOR( "FISH_POOR" ); @@ -1240,7 +1245,9 @@ static bool are_requirements_nearby( const std::vector &loot_spots, p.backlog.front().id() == ACT_MULTIPLE_CHOP_TREES || activity_to_restore == ACT_MULTIPLE_CHOP_TREES || p.backlog.front().id() == ACT_MULTIPLE_FISH || - activity_to_restore == ACT_MULTIPLE_FISH; + activity_to_restore == ACT_MULTIPLE_FISH || + p.backlog.front().id() == ACT_MULTIPLE_MINE || + activity_to_restore == ACT_MULTIPLE_MINE; bool found_welder = false; for( item *elem : p.inv_dump() ) { if( elem->has_quality( qual_WELD ) ) { @@ -1443,6 +1450,20 @@ static activity_reason_info can_do_activity_there( const activity_id &act, playe p.activity_vehicle_part_index = -1; return activity_reason_info::fail( NO_ZONE ); } + if( act == ACT_MULTIPLE_MINE ) { + if( !g->m.has_flag( "MINEABLE", src_loc ) ) { + return activity_reason_info::fail( NO_ZONE ); + } + std::vector mining_inv = p.items_with( []( const item & itm ) { + return ( itm.has_flag( flag_DIG_TOOL ) && !itm.type->can_use( "JACKHAMMER" ) ) || + ( itm.type->can_use( "JACKHAMMER" ) && itm.ammo_sufficient() ); + } ); + if( mining_inv.empty() ) { + return activity_reason_info::fail( NEEDS_MINING ); + } else { + return activity_reason_info::ok( NEEDS_MINING ); + } + } if( act == ACT_MULTIPLE_FISH ) { if( !g->m.has_flag( flag_FISHABLE, src_loc ) ) { return activity_reason_info::fail( NO_ZONE ); @@ -1637,7 +1658,8 @@ static std::vector> requirements_map( player p.backlog.front().id() == ACT_MULTIPLE_CHOP_TREES || p.backlog.front().id() == ACT_VEHICLE_DECONSTRUCTION || p.backlog.front().id() == ACT_VEHICLE_REPAIR || - p.backlog.front().id() == ACT_MULTIPLE_FISH; + p.backlog.front().id() == ACT_MULTIPLE_FISH || + p.backlog.front().id() == ACT_MULTIPLE_MINE; // where it is, what it is, how much of it, and how much in total is required of that item. std::vector> final_map; std::vector loot_spots; @@ -1812,10 +1834,10 @@ static std::vector> requirements_map( player for( const std::vector &elem : tool_comps ) { bool line_found = false; for( const tool_comp &comp_elem : elem ) { - if( line_found || comp_elem.count <= 0 ) { + if( line_found || comp_elem.count < -1 ) { break; } - int quantity_required = comp_elem.count; + int quantity_required = std::max( 1, comp_elem.count ); int item_quantity = 0; auto it = requirement_map.begin(); int remainder = 0; @@ -1976,8 +1998,8 @@ static bool tidy_activity( player &p, const tripoint &src_loc, for( item *inv_elem : p.inv_dump() ) { if( inv_elem->has_var( "activity_var" ) ) { inv_elem->erase_var( "activity_var" ); - item_location loc( p, inv_elem ); - p.drop( loc, src_loc ); + put_into_vehicle_or_drop( p, item_drop_reason::deliberate, { *inv_elem }, src_loc ); + p.i_rem( inv_elem ); } } } @@ -2033,7 +2055,8 @@ static bool fetch_activity( player &p, const tripoint &src_loc, p.backlog.front().id() == ACT_VEHICLE_REPAIR || p.backlog.front().id() == ACT_MULTIPLE_BUTCHER || p.backlog.front().id() == ACT_MULTIPLE_CHOP_TREES || - p.backlog.front().id() == ACT_MULTIPLE_FISH ) ) { + p.backlog.front().id() == ACT_MULTIPLE_FISH || + p.backlog.front().id() == ACT_MULTIPLE_MINE ) ) { if( it.volume() > volume_allowed || it.weight() > weight_allowed ) { continue; } @@ -2376,6 +2399,52 @@ static int chop_moves( player &p, item *it ) return moves; } +static bool mine_activity( player &p, const tripoint &src_loc ) +{ + std::vector mining_inv = p.items_with( []( const item & itm ) { + return ( itm.has_flag( flag_DIG_TOOL ) && !itm.type->can_use( "JACKHAMMER" ) ) || + ( itm.type->can_use( "JACKHAMMER" ) && itm.ammo_sufficient() ); + } ); + if( mining_inv.empty() || p.is_mounted() || p.is_underwater() || g->m.veh_at( src_loc ) || + !g->m.has_flag( "MINEABLE", src_loc ) ) { + return false; + } + item *chosen_item = nullptr; + bool powered = false; + // is it a pickaxe or jackhammer? + for( item *elem : mining_inv ) { + if( chosen_item == nullptr ) { + chosen_item = elem; + if( elem->type->can_use( "JACKHAMMER" ) ) { + powered = true; + } + } else { + // prioritise powered tools + if( chosen_item->type->can_use( "PICKAXE" ) && elem->type->can_use( "JACKHAMMER" ) ) { + chosen_item = elem; + powered = true; + break; + } + } + } + if( chosen_item == nullptr ) { + return false; + } + int moves = to_moves( powered ? 30_minutes : 20_minutes ); + if( !powered ) { + moves += ( ( MAX_STAT + 4 ) - std::min( p.str_cur, MAX_STAT ) ) * to_moves( 5_minutes ); + } + if( g->m.move_cost( src_loc ) == 2 ) { + // We're breaking up some flat surface like pavement, which is much easier + moves /= 2; + } + p.assign_activity( powered ? ACT_JACKHAMMER : ACT_PICKAXE, moves, -1, + p.get_item_position( chosen_item ) ); + p.activity.placement = g->m.getabs( src_loc ); + return true; + +} + static bool chop_tree_activity( player &p, const tripoint &src_loc ) { item *best_qual = p.best_quality_item( qual_AXE ); @@ -2437,6 +2506,9 @@ static zone_type_id get_zone_for_act( const tripoint &src_loc, const zone_manage if( act_id == ACT_MULTIPLE_FISH ) { ret = zone_type_FISHING_SPOT; } + if( act_id == ACT_MULTIPLE_MINE ) { + ret = zone_type_MINING; + } if( src_loc != tripoint_zero && act_id == ACT_FETCH_REQUIRED ) { const zone_data *zd = mgr.get_zone_at( g->m.getabs( src_loc ) ); if( zd ) { @@ -2585,6 +2657,7 @@ static requirement_check_result generic_multi_activity_check_requirement( player act_id == ACT_VEHICLE_DECONSTRUCTION || act_id == ACT_VEHICLE_REPAIR || act_id == ACT_MULTIPLE_FISH || + act_id == ACT_MULTIPLE_MINE || ( act_id == ACT_MULTIPLE_CONSTRUCTION && !g->m.partial_con_at( src_loc ) ); // some activities require the target tile to be part of a zone. @@ -2610,7 +2683,7 @@ static requirement_check_result generic_multi_activity_check_requirement( player reason == NEEDS_TILLING || reason == NEEDS_CHOPPING || reason == NEEDS_BUTCHERING || reason == NEEDS_BIG_BUTCHERING || reason == NEEDS_VEH_DECONST || reason == NEEDS_VEH_REPAIR || reason == NEEDS_TREE_CHOPPING || - reason == NEEDS_FISHING ) { + reason == NEEDS_FISHING || reason == NEEDS_MINING ) { // we can do it, but we need to fetch some stuff first // before we set the task to fetch components - is it even worth it? are the components anywhere? requirement_id what_we_need; @@ -2652,6 +2725,8 @@ static requirement_check_result generic_multi_activity_check_requirement( player const requirement_id req_id( ran_str ); requirement_data::save_requirement( reqs, req_id ); what_we_need = req_id; + } else if( reason == NEEDS_MINING ) { + what_we_need = requirement_id( "mining_standard" ); } else if( reason == NEEDS_TILLING || reason == NEEDS_PLANTING || reason == NEEDS_CHOPPING || reason == NEEDS_BUTCHERING || reason == NEEDS_BIG_BUTCHERING || reason == NEEDS_TREE_CHOPPING || reason == NEEDS_FISHING ) { @@ -2686,8 +2761,9 @@ static requirement_check_result generic_multi_activity_check_requirement( player } bool tool_pickup = reason == NEEDS_TILLING || reason == NEEDS_PLANTING || reason == NEEDS_CHOPPING || reason == NEEDS_BUTCHERING || reason == NEEDS_BIG_BUTCHERING || - reason == NEEDS_TREE_CHOPPING || reason == NEEDS_VEH_DECONST || reason == NEEDS_VEH_REPAIR; - // is it even worth fetching anything if there isn't enough nearby? + reason == NEEDS_TREE_CHOPPING || reason == NEEDS_VEH_DECONST || reason == NEEDS_VEH_REPAIR || + reason == NEEDS_MINING; + // is it even worth fetching anything if there isnt enough nearby? if( !are_requirements_nearby( tool_pickup ? loot_zone_spots : combined_spots, what_we_need, p, act_id, tool_pickup, src_loc ) ) { p.add_msg_if_player( m_info, _( "The required items are not available to complete this task." ) ); @@ -2820,6 +2896,12 @@ static bool generic_multi_activity_do( player &p, const activity_id &act_id, p.get_item_position( best_rod ), best_rod->tname() ); p.activity.coord_set = g->get_fishable_locations( ACTIVITY_SEARCH_DISTANCE, src_loc ); return false; + } else if( reason == NEEDS_MINING ) { + // if have enough batteries to continue etc. + p.backlog.push_front( act_id ); + if( mine_activity( p, src_loc ) ) { + return false; + } } else if( reason == NEEDS_VEH_DECONST ) { if( vehicle_activity( p, src_loc, p.activity_vehicle_part_index, 'o' ) ) { p.backlog.push_front( act_id ); diff --git a/src/clzones.cpp b/src/clzones.cpp index fe0893d487919..5ef71b73a54f3 100644 --- a/src/clzones.cpp +++ b/src/clzones.cpp @@ -75,6 +75,9 @@ zone_manager::zone_manager() types.emplace( zone_type_id( "FISHING_SPOT" ), zone_type( translate_marker( "Fishing Spot" ), translate_marker( "Designate an area to fish from." ) ) ); + types.emplace( zone_type_id( "MINING" ), + zone_type( translate_marker( "Mine Terrain" ), + translate_marker( "Designate an area to mine." ) ) ); types.emplace( zone_type_id( "VEHICLE_DECONSTRUCT" ), zone_type( translate_marker( "Vehicle Deconstruct Zone" ), translate_marker( "Any vehicles in this area are marked for deconstruction." ) ) ); diff --git a/src/handle_action.cpp b/src/handle_action.cpp index f46dac1d7b2bc..419dab03a3fe7 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -74,6 +74,7 @@ static const activity_id ACT_MULTIPLE_CHOP_PLANKS( "ACT_MULTIPLE_CHOP_PLANKS" ); static const activity_id ACT_MULTIPLE_CHOP_TREES( "ACT_MULTIPLE_CHOP_TREES" ); static const activity_id ACT_MULTIPLE_CONSTRUCTION( "ACT_MULTIPLE_CONSTRUCTION" ); static const activity_id ACT_MULTIPLE_FARM( "ACT_MULTIPLE_FARM" ); +static const activity_id ACT_MULTIPLE_MINE( "ACT_MULTIPLE_MINE" ); static const activity_id ACT_PULP( "ACT_PULP" ); static const activity_id ACT_SPELLCASTING( "ACT_SPELLCASTING" ); static const activity_id ACT_VEHICLE_DECONSTRUCTION( "ACT_VEHICLE_DECONSTRUCTION" ); @@ -1081,7 +1082,8 @@ static void loot() Multichopplanks = 512, Multideconvehicle = 1024, Multirepairvehicle = 2048, - MultiButchery = 4096 + MultiButchery = 4096, + MultiMining = 8192 }; player &u = g->u; @@ -1108,6 +1110,7 @@ static void loot() u.pos() ) ? Multideconvehicle : 0; flags |= g->check_near_zone( zone_type_id( "VEHICLE_REPAIR" ), u.pos() ) ? Multirepairvehicle : 0; flags |= g->check_near_zone( zone_type_id( "LOOT_CORPSE" ), u.pos() ) ? MultiButchery : 0; + flags |= g->check_near_zone( zone_type_id( "MINING" ), u.pos() ) ? MultiMining : 0; if( flags == 0 ) { add_msg( m_info, _( "There is no compatible zone nearby." ) ); add_msg( m_info, _( "Compatible zones are %s and %s" ), @@ -1159,6 +1162,10 @@ static void loot() menu.addentry_desc( MultiButchery, true, 'B', _( "Butcher corpses" ), _( "Auto-butcher anything in corpse loot zones - auto-fetch tools." ) ); } + if( flags & MultiMining ) { + menu.addentry_desc( MultiMining, true, 'M', _( "Mine Area" ), + _( "Auto-mine anything in mining zone - auto-fetch tools." ) ); + } menu.query(); flags = ( menu.ret >= 0 ) ? menu.ret : None; @@ -1194,6 +1201,9 @@ static void loot() case MultiButchery: u.assign_activity( ACT_MULTIPLE_BUTCHER ); break; + case MultiMining: + u.assign_activity( ACT_MULTIPLE_MINE ); + break; default: debugmsg( "Unsupported flag" ); break; diff --git a/src/iuse.cpp b/src/iuse.cpp index 5a243dcaef6ad..c0445f3f50df9 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -3258,7 +3258,7 @@ int iuse::jackhammer( player *p, item *it, bool, const tripoint &pos ) } p->assign_activity( ACT_JACKHAMMER, moves, -1, p->get_item_position( it ) ); - p->activity.placement = pnt; + p->activity.placement = g->m.getabs( pnt ); p->add_msg_if_player( _( "You start drilling into the %1$s with your %2$s." ), g->m.tername( pnt ), it->tname() ); @@ -3314,7 +3314,7 @@ int iuse::pickaxe( player *p, item *it, bool, const tripoint &pos ) } p->assign_activity( ACT_PICKAXE, moves, -1, p->get_item_position( it ) ); - p->activity.placement = pnt; + p->activity.placement = g->m.getabs( pnt ); p->add_msg_if_player( _( "You strike the %1$s with your %2$s." ), g->m.tername( pnt ), it->tname() ); return 0; // handled when the activity finishes diff --git a/src/npctalk.cpp b/src/npctalk.cpp index e1f9480c5a180..37e5805b15558 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -2574,6 +2574,7 @@ void talk_effect_t::parse_string_effect( const std::string &effect_id, const Jso WRAP( do_chop_trees ), WRAP( do_fishing ), WRAP( do_construction ), + WRAP( do_mining ), WRAP( do_read ), WRAP( do_butcher ), WRAP( do_farming ), diff --git a/src/npctalk.h b/src/npctalk.h index 79da5d35ac5e0..4aa558fc29679 100644 --- a/src/npctalk.h +++ b/src/npctalk.h @@ -38,6 +38,7 @@ void buy_100_logs( npc & ); void start_trade( npc & ); void sort_loot( npc & ); void do_construction( npc & ); +void do_mining( npc & ); void do_read( npc & ); void do_chop_plank( npc & ); void do_vehicle_deconstruct( npc & ); diff --git a/src/npctalk_funcs.cpp b/src/npctalk_funcs.cpp index 7ecd57649739e..47db4750a9599 100644 --- a/src/npctalk_funcs.cpp +++ b/src/npctalk_funcs.cpp @@ -57,6 +57,7 @@ static const activity_id ACT_MULTIPLE_CHOP_TREES( "ACT_MULTIPLE_CHOP_TREES" ); static const activity_id ACT_MULTIPLE_CONSTRUCTION( "ACT_MULTIPLE_CONSTRUCTION" ); static const activity_id ACT_MULTIPLE_FARM( "ACT_MULTIPLE_FARM" ); static const activity_id ACT_MULTIPLE_FISH( "ACT_MULTIPLE_FISH" ); +static const activity_id ACT_MULTIPLE_MINE( "ACT_MULTIPLE_MINE" ); static const activity_id ACT_VEHICLE_DECONSTRUCTION( "ACT_VEHICLE_DECONSTRUCTION" ); static const activity_id ACT_VEHICLE_REPAIR( "ACT_VEHICLE_REPAIR" ); static const activity_id ACT_WAIT_NPC( "ACT_WAIT_NPC" ); @@ -219,6 +220,11 @@ void talk_function::do_construction( npc &p ) p.assign_activity( ACT_MULTIPLE_CONSTRUCTION ); } +void talk_function::do_mining( npc &p ) +{ + p.assign_activity( ACT_MULTIPLE_MINE ); +} + void talk_function::do_read( npc &p ) { p.do_npc_read();