SHARE
TWEET

Untitled

a guest May 19th, 2017 43 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. bool game::handle_liquid( item &liquid, item * const source, const int radius,
  2.                           const tripoint * const source_pos,
  3.                           const vehicle * const source_veh,
  4.                           const monster * const source_mon)
  5. {
  6.     if( !liquid.made_of(LIQUID) ) {
  7.         dbg(D_ERROR) << "game:handle_liquid: Tried to handle_liquid a non-liquid!";
  8.         debugmsg("Tried to handle_liquid a non-liquid!");
  9.         // "canceled by the user" because we *can* not handle it.
  10.         return false;
  11.     }
  12.  
  13.     const auto create_activity = [&]() {
  14.         if( source_veh != nullptr ) {
  15.             u.assign_activity( activity_id( "ACT_FILL_LIQUID" ) );
  16.             serialize_liquid_source( u.activity, *source_veh, liquid.typeId() );
  17.             return true;
  18.         } else if( source_pos != nullptr ) {
  19.             u.assign_activity( activity_id( "ACT_FILL_LIQUID" ) );
  20.             serialize_liquid_source( u.activity, *source_pos, liquid );
  21.             return true;
  22.         }
  23.         else if (source_mon != nullptr) {
  24.             u.assign_activity(activity_id("ACT_FILL_LIQUID"));
  25.             serialize_liquid_source(u.activity, *source_mon, liquid);
  26.             return true;
  27.         }
  28.         else {
  29.             return false;
  30.         }
  31.     };
  32.  
  33.     const std::string liquid_name = liquid.display_name( liquid.charges );
  34.  
  35.     uimenu menu;
  36.     menu.return_invalid = true;
  37.     if( source_pos != nullptr ) {
  38.         menu.text = string_format( _( "What to do with the %s from %s?" ), liquid_name.c_str(), m.name( *source_pos ).c_str() );
  39.     } else if( source_veh != nullptr ) {
  40.         menu.text = string_format( _( "What to do with the %s from the %s?" ), liquid_name.c_str(), source_veh->name.c_str() );
  41.  
  42.     } else if( source_mon != nullptr ) {
  43.         menu.text = string_format( _( "What to do with the %s from the %s?" ), liquid_name.c_str(),
  44.                                    source_mon->disp_name().c_str() );
  45.     } else {
  46.         menu.text = string_format( _( "What to do with the %s?" ), liquid_name.c_str() );
  47.     }
  48.     std::vector<std::function<void()>> actions;
  49.     // Small check to avoid players sucking milk directly from the animal.
  50.     if (!source_mon == true) {
  51.         if (u.can_consume(liquid)) {
  52.             menu.addentry(-1, true, 'e', _("Consume it"));
  53.             actions.emplace_back([&]() {
  54.                 // consume_item already consumes moves.
  55.                 u.consume_item(liquid);
  56.             });
  57.         }
  58.     }
  59.  
  60.     // This handles containers found anywhere near the player, including on the map and in vehicle storage.
  61.     menu.addentry( -1, true, 'c', _( "Pour into a container" ) );
  62.     actions.emplace_back( [&]() {
  63.         item_location target = game_menus::inv::container_for( u, liquid, radius );
  64.         item *const cont = target.get_item();
  65.  
  66.         if( cont == nullptr || cont->is_null() ) {
  67.             add_msg( _( "Never mind." ) );
  68.             return;
  69.         }
  70.         if( cont == source && source != nullptr ) {
  71.             add_msg( m_info, _( "That's the same container!" ) );
  72.             return; // The user has intended to do something, but mistyped.
  73.         }
  74.         const int item_index = u.get_item_position( cont );
  75.         // Currently activities can only store item position in the players inventory,
  76.         // not on ground or similar. TODO: implement storing arbitrary container locations.
  77.         if( item_index != INT_MIN && create_activity() ) {
  78.             serialize_liquid_target( u.activity, item_index );
  79.         } else if( u.pour_into( *cont, liquid ) ) {
  80.             if( cont->needs_processing() ) {
  81.                 // Polymorphism fail, have to introspect into the type to set the target container as active.
  82.                 switch( target.where() ) {
  83.                 case item_location::type::map:
  84.                     m.make_active( target );
  85.                     break;
  86.                 case item_location::type::vehicle:
  87.                     m.veh_at( target.position() )->make_active( target );
  88.                     break;
  89.                 case item_location::type::character:
  90.                 case item_location::type::invalid:
  91.                     break;
  92.                 }
  93.             }
  94.             u.mod_moves( -100 );
  95.         }
  96.     } );
  97.  
  98.     // This handles liquids stored in vehicle parts directly (e.g. tanks).
  99.     std::set<vehicle *> opts;
  100.     for( const auto &e : g->m.points_in_radius( g->u.pos(), 1 ) ) {
  101.         auto veh = g->m.veh_at( e );
  102.         if( veh && std::any_of( veh->parts.begin(), veh->parts.end(), [&liquid]( const vehicle_part &pt ) {
  103.             // cannot refill using active liquids (those that rot) due to #18570
  104.             return !liquid.active && pt.can_reload( liquid.typeId() );
  105.         } ) ) {
  106.             opts.insert( veh );
  107.         }
  108.     }
  109.     for( auto veh : opts ) {
  110.         if( veh == source_veh ) {
  111.             continue;
  112.         }
  113.         menu.addentry( -1, true, MENU_AUTOASSIGN, _( "Fill nearby vehicle %s" ), veh->name.c_str() );
  114.         actions.emplace_back( [&, veh]() {
  115.             if( create_activity() ) {
  116.                 serialize_liquid_target( u.activity, *veh );
  117.             } else if( u.pour_into( *veh, liquid ) ) {
  118.                 u.mod_moves( -1000 ); // consistent with veh_interact::do_refill activity
  119.             }
  120.         } );
  121.     }
  122.  
  123.     for( auto &target_pos : m.points_in_radius( u.pos(), 1 ) ) {
  124.         if( !iexamine::has_keg( target_pos ) ) {
  125.             continue;
  126.         }
  127.         if( source_pos != nullptr && *source_pos == target_pos ) {
  128.             continue;
  129.         }
  130.         const std::string dir = direction_name( direction_from( u.pos(), target_pos ) );
  131.         menu.addentry( -1, true, MENU_AUTOASSIGN, _( "Pour into an adjacent keg (%s)" ), dir.c_str() );
  132.         actions.emplace_back( [&, target_pos]() {
  133.             if( create_activity() ) {
  134.                 serialize_liquid_target( u.activity, target_pos );
  135.             } else {
  136.                 iexamine::pour_into_keg( target_pos, liquid );
  137.                 u.mod_moves( -100 );
  138.             }
  139.         } );
  140.     }
  141.  
  142.     menu.addentry( -1, true, 'g', _( "Pour on the ground" ) );
  143.     actions.emplace_back( [&]() {
  144.         // From infinite source to the ground somewhere else. The target has
  145.         // infinite space and the liquid can not be used from there anyway.
  146.         if( liquid.has_infinite_charges() && source_pos != nullptr ) {
  147.             add_msg( m_info, _( "Clearing out the %s would take forever." ), m.name( *source_pos ).c_str() );
  148.             return;
  149.         }
  150.  
  151.         tripoint target_pos = u.pos();
  152.         const std::string liqstr = string_format( _( "Pour %s where?" ), liquid_name.c_str() );
  153.  
  154.         refresh_all();
  155.         if( !choose_adjacent( liqstr, target_pos ) ) {
  156.             return;
  157.         }
  158.  
  159.         if( source_pos != nullptr && *source_pos == target_pos ) {
  160.             add_msg( m_info, _( "That's where you took it from!" ) );
  161.             return;
  162.         }
  163.         if( !m.can_put_items_ter_furn( target_pos ) ) {
  164.             add_msg( m_info, _( "You can't pour there!" ) );
  165.             return;
  166.         }
  167.  
  168.         if( create_activity() ) {
  169.             serialize_liquid_target( u.activity, target_pos );
  170.         } else {
  171.             m.add_item_or_charges( target_pos, liquid );
  172.             liquid.charges = 0;
  173.             u.mod_moves( -100 );
  174.         }
  175.     } );
  176.     if( liquid.rotten() ) {
  177.         // Pre-select this one as it is the most likely one for rotten liquids
  178.         menu.selected = menu.entries.size() - 1;
  179.     }
  180.  
  181.     if( menu.entries.empty() ) {
  182.         return false;
  183.     }
  184.  
  185.     menu.query();
  186.     refresh_all();
  187.     const size_t chosen = static_cast<size_t>( menu.ret );
  188.     if( chosen >= actions.size() ) {
  189.         add_msg( _( "Never mind." ) );
  190.         // Explicitly canceled all options (container, drink, pour).
  191.         return false;
  192.     }
  193.  
  194.     actions[chosen]();
  195.     return true;
  196. }
RAW Paste Data
Want to get better at C++?
Learn to code C++ in 2017
Pastebin PRO Summer Special!
Get 40% OFF on Pastebin PRO accounts!
Top