Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- bool game::handle_liquid( item &liquid, item * const source, const int radius,
- const tripoint * const source_pos,
- const vehicle * const source_veh,
- const monster * const source_mon)
- {
- if( !liquid.made_of(LIQUID) ) {
- dbg(D_ERROR) << "game:handle_liquid: Tried to handle_liquid a non-liquid!";
- debugmsg("Tried to handle_liquid a non-liquid!");
- // "canceled by the user" because we *can* not handle it.
- return false;
- }
- const auto create_activity = [&]() {
- if( source_veh != nullptr ) {
- u.assign_activity( activity_id( "ACT_FILL_LIQUID" ) );
- serialize_liquid_source( u.activity, *source_veh, liquid.typeId() );
- return true;
- } else if( source_pos != nullptr ) {
- u.assign_activity( activity_id( "ACT_FILL_LIQUID" ) );
- serialize_liquid_source( u.activity, *source_pos, liquid );
- return true;
- }
- else if (source_mon != nullptr) {
- u.assign_activity(activity_id("ACT_FILL_LIQUID"));
- serialize_liquid_source(u.activity, *source_mon, liquid);
- return true;
- }
- else {
- return false;
- }
- };
- const std::string liquid_name = liquid.display_name( liquid.charges );
- uimenu menu;
- menu.return_invalid = true;
- if( source_pos != nullptr ) {
- menu.text = string_format( _( "What to do with the %s from %s?" ), liquid_name.c_str(), m.name( *source_pos ).c_str() );
- } else if( source_veh != nullptr ) {
- menu.text = string_format( _( "What to do with the %s from the %s?" ), liquid_name.c_str(), source_veh->name.c_str() );
- } else if( source_mon != nullptr ) {
- menu.text = string_format( _( "What to do with the %s from the %s?" ), liquid_name.c_str(),
- source_mon->disp_name().c_str() );
- } else {
- menu.text = string_format( _( "What to do with the %s?" ), liquid_name.c_str() );
- }
- std::vector<std::function<void()>> actions;
- // Small check to avoid players sucking milk directly from the animal.
- if (!source_mon == true) {
- if (u.can_consume(liquid)) {
- menu.addentry(-1, true, 'e', _("Consume it"));
- actions.emplace_back([&]() {
- // consume_item already consumes moves.
- u.consume_item(liquid);
- });
- }
- }
- // This handles containers found anywhere near the player, including on the map and in vehicle storage.
- menu.addentry( -1, true, 'c', _( "Pour into a container" ) );
- actions.emplace_back( [&]() {
- item_location target = game_menus::inv::container_for( u, liquid, radius );
- item *const cont = target.get_item();
- if( cont == nullptr || cont->is_null() ) {
- add_msg( _( "Never mind." ) );
- return;
- }
- if( cont == source && source != nullptr ) {
- add_msg( m_info, _( "That's the same container!" ) );
- return; // The user has intended to do something, but mistyped.
- }
- const int item_index = u.get_item_position( cont );
- // Currently activities can only store item position in the players inventory,
- // not on ground or similar. TODO: implement storing arbitrary container locations.
- if( item_index != INT_MIN && create_activity() ) {
- serialize_liquid_target( u.activity, item_index );
- } else if( u.pour_into( *cont, liquid ) ) {
- if( cont->needs_processing() ) {
- // Polymorphism fail, have to introspect into the type to set the target container as active.
- switch( target.where() ) {
- case item_location::type::map:
- m.make_active( target );
- break;
- case item_location::type::vehicle:
- m.veh_at( target.position() )->make_active( target );
- break;
- case item_location::type::character:
- case item_location::type::invalid:
- break;
- }
- }
- u.mod_moves( -100 );
- }
- } );
- // This handles liquids stored in vehicle parts directly (e.g. tanks).
- std::set<vehicle *> opts;
- for( const auto &e : g->m.points_in_radius( g->u.pos(), 1 ) ) {
- auto veh = g->m.veh_at( e );
- if( veh && std::any_of( veh->parts.begin(), veh->parts.end(), [&liquid]( const vehicle_part &pt ) {
- // cannot refill using active liquids (those that rot) due to #18570
- return !liquid.active && pt.can_reload( liquid.typeId() );
- } ) ) {
- opts.insert( veh );
- }
- }
- for( auto veh : opts ) {
- if( veh == source_veh ) {
- continue;
- }
- menu.addentry( -1, true, MENU_AUTOASSIGN, _( "Fill nearby vehicle %s" ), veh->name.c_str() );
- actions.emplace_back( [&, veh]() {
- if( create_activity() ) {
- serialize_liquid_target( u.activity, *veh );
- } else if( u.pour_into( *veh, liquid ) ) {
- u.mod_moves( -1000 ); // consistent with veh_interact::do_refill activity
- }
- } );
- }
- for( auto &target_pos : m.points_in_radius( u.pos(), 1 ) ) {
- if( !iexamine::has_keg( target_pos ) ) {
- continue;
- }
- if( source_pos != nullptr && *source_pos == target_pos ) {
- continue;
- }
- const std::string dir = direction_name( direction_from( u.pos(), target_pos ) );
- menu.addentry( -1, true, MENU_AUTOASSIGN, _( "Pour into an adjacent keg (%s)" ), dir.c_str() );
- actions.emplace_back( [&, target_pos]() {
- if( create_activity() ) {
- serialize_liquid_target( u.activity, target_pos );
- } else {
- iexamine::pour_into_keg( target_pos, liquid );
- u.mod_moves( -100 );
- }
- } );
- }
- menu.addentry( -1, true, 'g', _( "Pour on the ground" ) );
- actions.emplace_back( [&]() {
- // From infinite source to the ground somewhere else. The target has
- // infinite space and the liquid can not be used from there anyway.
- if( liquid.has_infinite_charges() && source_pos != nullptr ) {
- add_msg( m_info, _( "Clearing out the %s would take forever." ), m.name( *source_pos ).c_str() );
- return;
- }
- tripoint target_pos = u.pos();
- const std::string liqstr = string_format( _( "Pour %s where?" ), liquid_name.c_str() );
- refresh_all();
- if( !choose_adjacent( liqstr, target_pos ) ) {
- return;
- }
- if( source_pos != nullptr && *source_pos == target_pos ) {
- add_msg( m_info, _( "That's where you took it from!" ) );
- return;
- }
- if( !m.can_put_items_ter_furn( target_pos ) ) {
- add_msg( m_info, _( "You can't pour there!" ) );
- return;
- }
- if( create_activity() ) {
- serialize_liquid_target( u.activity, target_pos );
- } else {
- m.add_item_or_charges( target_pos, liquid );
- liquid.charges = 0;
- u.mod_moves( -100 );
- }
- } );
- if( liquid.rotten() ) {
- // Pre-select this one as it is the most likely one for rotten liquids
- menu.selected = menu.entries.size() - 1;
- }
- if( menu.entries.empty() ) {
- return false;
- }
- menu.query();
- refresh_all();
- const size_t chosen = static_cast<size_t>( menu.ret );
- if( chosen >= actions.size() ) {
- add_msg( _( "Never mind." ) );
- // Explicitly canceled all options (container, drink, pour).
- return false;
- }
- actions[chosen]();
- return true;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement