bool vehicle_part::fill_with( item &liquid, long qty ) { if( !is_tank() || !can_reload( liquid ) ) { return false; } base.fill_with( liquid, qty ); return true; }
// Handles interactions with a vehicle in the examine menu. interact_results interact_with_vehicle( vehicle *veh, const tripoint &pos, int veh_root_part ) { if( veh == nullptr ) { return ITEMS_FROM_GROUND; } std::vector<std::string> menu_items; std::vector<uimenu_entry> options_message; const bool has_items_on_ground = g->m.sees_some_items( pos, g->u ); const bool items_are_sealed = g->m.has_flag( "SEALED", pos ); auto turret = veh->turret_query( pos ); const bool has_kitchen = ( veh->part_with_feature( veh_root_part, "KITCHEN" ) >= 0 ); const bool has_faucet = ( veh->part_with_feature( veh_root_part, "FAUCET" ) >= 0 ); const bool has_weldrig = ( veh->part_with_feature( veh_root_part, "WELDRIG" ) >= 0 ); const bool has_chemlab = ( veh->part_with_feature( veh_root_part, "CHEMLAB" ) >= 0 ); const bool has_purify = ( veh->part_with_feature( veh_root_part, "WATER_PURIFIER" ) >= 0 ); const bool has_controls = ( ( veh->part_with_feature( veh_root_part, "CONTROLS" ) >= 0 ) || ( veh->part_with_feature( veh_root_part, "CTRL_ELECTRONIC" ) >= 0 ) ); const int cargo_part = veh->part_with_feature( veh_root_part, "CARGO", false ); const bool from_vehicle = veh && cargo_part >= 0 && !veh->get_items( cargo_part ).empty(); const bool can_be_folded = veh->is_foldable(); const bool is_convertible = ( veh->tags.count( "convertible" ) > 0 ); const bool remotely_controlled = g->remoteveh() == veh; typedef enum { EXAMINE, CONTROL, GET_ITEMS, GET_ITEMS_ON_GROUND, FOLD_VEHICLE, UNLOAD_TURRET, RELOAD_TURRET, USE_HOTPLATE, FILL_CONTAINER, DRINK, USE_WELDER, USE_PURIFIER, PURIFY_TANK } options; uimenu selectmenu; selectmenu.addentry( EXAMINE, true, 'e', _( "Examine vehicle" ) ); if( has_controls ) { selectmenu.addentry( CONTROL, true, 'v', _( "Control vehicle" ) ); } if( from_vehicle ) { selectmenu.addentry( GET_ITEMS, true, 'g', _( "Get items" ) ); } if( has_items_on_ground && !items_are_sealed ) { selectmenu.addentry( GET_ITEMS_ON_GROUND, true, 'i', _( "Get items on the ground" ) ); } if( ( can_be_folded || is_convertible ) && !remotely_controlled ) { selectmenu.addentry( FOLD_VEHICLE, true, 'f', _( "Fold vehicle" ) ); } if( turret.can_unload() ) { selectmenu.addentry( UNLOAD_TURRET, true, 'u', _( "Unload %s" ), turret.name().c_str() ); } if( turret.can_reload() ) { selectmenu.addentry( RELOAD_TURRET, true, 'r', _( "Reload %s" ), turret.name().c_str() ); } if( ( has_kitchen || has_chemlab ) && veh->fuel_left( "battery" ) > 0 ) { selectmenu.addentry( USE_HOTPLATE, true, 'h', _( "Use the hotplate" ) ); } if( has_faucet && veh->fuel_left( "water_clean" ) > 0 ) { selectmenu.addentry( FILL_CONTAINER, true, 'c', _( "Fill a container with water" ) ); selectmenu.addentry( DRINK, true, 'd', _( "Have a drink" ) ); } if( has_weldrig && veh->fuel_left( "battery" ) > 0 ) { selectmenu.addentry( USE_WELDER, true, 'w', _( "Use the welding rig?" ) ); } if( has_purify && veh->fuel_left( "battery" ) > 0 ) { selectmenu.addentry( USE_PURIFIER, true, 'p', _( "Purify water in carried container" ) ); } if( has_purify && veh->fuel_left( "battery" ) > 0 && veh->fuel_left( "water" ) > 0 && veh->fuel_capacity( "water_clean" ) > veh->fuel_left( "water_clean" ) ) { selectmenu.addentry( PURIFY_TANK, true, 'P', _( "Purify water in vehicle's tank" ) ); } int choice; if( selectmenu.entries.size() == 1 ) { choice = selectmenu.entries.front().retval; } else { selectmenu.return_invalid = true; selectmenu.text = _( "Select an action" ); selectmenu.selected = 0; selectmenu.query(); choice = selectmenu.ret; } switch( static_cast<options>( choice ) ) { case USE_HOTPLATE: { item pseudo( "hotplate" ); itype_id ammo = pseudo.ammo_default(); pseudo.ammo_set( ammo, veh->drain( ammo, pseudo.ammo_capacity() ) ); if( pseudo.ammo_sufficient() ) { g->u.invoke_item( &pseudo ); pseudo.ammo_consume( pseudo.ammo_required(), g->u.pos() ); veh->refill( ammo, pseudo.ammo_remaining() ); } return DONE; } case FILL_CONTAINER: g->u.siphon( *veh, "water_clean" ); return DONE; case DRINK: { veh->drain( "water_clean", 1 ); item water( "water_clean", 0 ); g->u.eat( water ); g->u.moves -= 250; return DONE; } case USE_WELDER: { item pseudo( "welder" ); itype_id ammo = pseudo.ammo_default(); pseudo.ammo_set( ammo, veh->drain( ammo, pseudo.ammo_capacity() ) ); if( pseudo.ammo_sufficient() ) { g->u.invoke_item( &pseudo ); pseudo.ammo_consume( pseudo.ammo_required(), g->u.pos() ); veh->refill( ammo, pseudo.ammo_remaining() ); // Evil hack incoming auto &act = g->u.activity; if( act.type == ACT_REPAIR_ITEM ) { // Magic: first tell activity the item doesn't really exist act.index = INT_MIN; // Then tell it to search it on `pos` act.coords.push_back( pos ); // Finally tell it it is the vehicle part with weldrig act.values.resize( 2 ); act.values[1] = veh->part_with_feature( veh_root_part, "WELDRIG" ); } } return DONE; } case USE_PURIFIER: { item pseudo( "water_purifier" ); itype_id ammo = pseudo.ammo_default(); pseudo.ammo_set( ammo, veh->drain( ammo, pseudo.ammo_capacity() ) ); if( pseudo.ammo_sufficient() ) { g->u.invoke_item( &pseudo ); } veh->refill( ammo, pseudo.ammo_remaining() ); return DONE; } case PURIFY_TANK: { const int max_water = std::min( veh->fuel_left( "water" ), veh->fuel_capacity( "water_clean" ) - veh->fuel_left( "water_clean" ) ); const int purify_amount = std::min( veh->fuel_left( "battery" ), max_water ); veh->drain( "battery", purify_amount ); veh->drain( "water", purify_amount ); veh->refill( "water_clean", purify_amount ); return DONE; } case UNLOAD_TURRET: { g->unload( *turret.base() ); return DONE; } case RELOAD_TURRET: { item::reload_option opt = g->u.select_ammo( *turret.base(), true ); if( opt ) { g->u.assign_activity( ACT_RELOAD, opt.moves(), opt.qty() ); g->u.activity.targets.emplace_back( turret.base() ); g->u.activity.targets.push_back( std::move( opt.ammo ) ); } return DONE; } case FOLD_VEHICLE: veh->fold_up(); return DONE; case CONTROL: if( veh->interact_vehicle_locked() ) { veh->use_controls( pos ); } return DONE; case EXAMINE: g->exam_vehicle( *veh ); return DONE; case GET_ITEMS_ON_GROUND: return ITEMS_FROM_GROUND; case GET_ITEMS: return from_vehicle ? ITEMS_FROM_CARGO : ITEMS_FROM_GROUND; } return DONE; }
// Handles interactions with a vehicle in the examine menu. interact_results interact_with_vehicle( vehicle *veh, const tripoint &pos, int veh_root_part ) { if( veh == nullptr ) { return ITEMS_FROM_GROUND; } std::vector<std::string> menu_items; std::vector<uimenu_entry> options_message; const bool has_items_on_ground = g->m.sees_some_items( pos, g->u ); const bool items_are_sealed = g->m.has_flag( "SEALED", pos ); auto turret = veh->turret_query( pos ); const bool has_kitchen = ( veh->part_with_feature( veh_root_part, "KITCHEN" ) >= 0 ); const bool has_faucet = ( veh->part_with_feature( veh_root_part, "FAUCET" ) >= 0 ); const bool has_weldrig = ( veh->part_with_feature( veh_root_part, "WELDRIG" ) >= 0 ); const bool has_chemlab = ( veh->part_with_feature( veh_root_part, "CHEMLAB" ) >= 0 ); const bool has_purify = ( veh->part_with_feature( veh_root_part, "WATER_PURIFIER" ) >= 0 ); const bool has_controls = ( ( veh->part_with_feature( veh_root_part, "CONTROLS" ) >= 0 ) || ( veh->part_with_feature( veh_root_part, "CTRL_ELECTRONIC" ) >= 0 ) ); const int cargo_part = veh->part_with_feature( veh_root_part, "CARGO", false ); const bool from_vehicle = cargo_part >= 0 && !veh->get_items( cargo_part ).empty(); const bool can_be_folded = veh->is_foldable(); const bool is_convertible = ( veh->tags.count( "convertible" ) > 0 ); const bool remotely_controlled = g->remoteveh() == veh; const int washing_machine_part = veh->part_with_feature( veh_root_part, "WASHING_MACHINE" ); const bool has_washmachine = washing_machine_part >= 0; bool washing_machine_on = ( washing_machine_part == -1 ) ? false : veh->parts[washing_machine_part].enabled; const bool has_monster_capture = ( veh->part_with_feature( veh_root_part, "CAPTURE_MONSTER_VEH" ) >= 0 ); const int monster_capture_part = veh->part_with_feature( veh_root_part, "CAPTURE_MONSTER_VEH" ); typedef enum { EXAMINE, TRACK, CONTROL, CONTROL_ELECTRONICS, GET_ITEMS, GET_ITEMS_ON_GROUND, FOLD_VEHICLE, UNLOAD_TURRET, RELOAD_TURRET, USE_HOTPLATE, FILL_CONTAINER, DRINK, USE_WELDER, USE_PURIFIER, PURIFY_TANK, USE_WASHMACHINE, USE_MONSTER_CAPTURE } options; uimenu selectmenu; selectmenu.addentry( EXAMINE, true, 'e', _( "Examine vehicle" ) ); selectmenu.addentry( TRACK, true, keybind( "TOGGLE_TRACKING" ), veh->tracking_toggle_string() ); if( has_controls ) { selectmenu.addentry( CONTROL, true, 'v', _( "Control vehicle" ) ); selectmenu.addentry( CONTROL_ELECTRONICS, true, keybind( "CONTROL_MANY_ELECTRONICS" ), _( "Control multiple electronics" ) ); } if( has_washmachine ) { selectmenu.addentry( USE_WASHMACHINE, true, 'W', washing_machine_on ? _( "Deactivate the washing machine" ) : _( "Activate the washing machine (1.5 hours)" ) ); } if( from_vehicle && !washing_machine_on ) { selectmenu.addentry( GET_ITEMS, true, 'g', _( "Get items" ) ); } if( has_items_on_ground && !items_are_sealed ) { selectmenu.addentry( GET_ITEMS_ON_GROUND, true, 'i', _( "Get items on the ground" ) ); } if( ( can_be_folded || is_convertible ) && !remotely_controlled ) { selectmenu.addentry( FOLD_VEHICLE, true, 'f', _( "Fold vehicle" ) ); } if( turret.can_unload() ) { selectmenu.addentry( UNLOAD_TURRET, true, 'u', _( "Unload %s" ), turret.name().c_str() ); } if( turret.can_reload() ) { selectmenu.addentry( RELOAD_TURRET, true, 'r', _( "Reload %s" ), turret.name().c_str() ); } if( ( has_kitchen || has_chemlab ) && veh->fuel_left( "battery" ) > 0 ) { selectmenu.addentry( USE_HOTPLATE, true, 'h', _( "Use the hotplate" ) ); } if( has_faucet && veh->fuel_left( "water_clean" ) > 0 ) { selectmenu.addentry( FILL_CONTAINER, true, 'c', _( "Fill a container with water" ) ); selectmenu.addentry( DRINK, true, 'd', _( "Have a drink" ) ); } if( has_weldrig && veh->fuel_left( "battery" ) > 0 ) { selectmenu.addentry( USE_WELDER, true, 'w', _( "Use the welding rig?" ) ); } if( has_purify ) { bool can_purify = veh->fuel_left( "battery" ) >= item::find_type( "water_purifier" )->charges_to_use(); selectmenu.addentry( USE_PURIFIER, can_purify, 'p', _( "Purify water in carried container" ) ); selectmenu.addentry( PURIFY_TANK, can_purify && veh->fuel_left( "water" ), 'P', _( "Purify water in vehicle tank" ) ); } if( has_monster_capture ) { selectmenu.addentry( USE_MONSTER_CAPTURE, true, 'G', _( "Capture or release a creature" ) ); } int choice; if( selectmenu.entries.size() == 1 ) { choice = selectmenu.entries.front().retval; } else { selectmenu.return_invalid = true; selectmenu.text = _( "Select an action" ); selectmenu.selected = 0; selectmenu.query(); choice = selectmenu.ret; } auto veh_tool = [&]( const itype_id & obj ) { item pseudo( obj ); if( veh->fuel_left( "battery" ) < pseudo.ammo_required() ) { return false; } auto qty = pseudo.ammo_capacity() - veh->discharge_battery( pseudo.ammo_capacity() ); pseudo.ammo_set( "battery", qty ); g->u.invoke_item( &pseudo ); veh->charge_battery( pseudo.ammo_remaining() ); return true; }; switch( static_cast<options>( choice ) ) { case USE_MONSTER_CAPTURE: { veh->use_monster_capture( monster_capture_part, pos ); return DONE; } case USE_HOTPLATE: veh_tool( "hotplate" ); return DONE; case USE_WASHMACHINE: { veh->use_washing_machine( washing_machine_part ); return DONE; } case FILL_CONTAINER: g->u.siphon( *veh, "water_clean" ); return DONE; case DRINK: { item water( "water_clean", 0 ); if( g->u.eat( water ) ) { veh->drain( "water_clean", 1 ); g->u.moves -= 250; } return DONE; } case USE_WELDER: { if( veh_tool( "welder" ) ) { // Evil hack incoming auto &act = g->u.activity; if( act.id() == activity_id( "ACT_REPAIR_ITEM" ) ) { // Magic: first tell activity the item doesn't really exist act.index = INT_MIN; // Then tell it to search it on `pos` act.coords.push_back( pos ); // Finally tell if it is the vehicle part with welding rig act.values.resize( 2 ); act.values[1] = veh->part_with_feature( veh_root_part, "WELDRIG" ); } } return DONE; } case USE_PURIFIER: veh_tool( "water_purifier" ); return DONE; case PURIFY_TANK: { auto sel = []( const vehicle_part & pt ) { return pt.is_tank() && pt.ammo_current() == "water"; }; auto title = string_format( _( "Purify <color_%s>water</color> in tank" ), get_all_colors().get_name( item::find_type( "water" )->color ).c_str() ); auto &tank = veh_interact::select_part( *veh, sel, title ); if( tank ) { double cost = item::find_type( "water_purifier" )->charges_to_use(); if( veh->fuel_left( "battery" ) < tank.ammo_remaining() * cost ) { //~ $1 - vehicle name, $2 - part name add_msg( m_bad, _( "Insufficient power to purify the contents of the %1$s's %2$s" ), veh->name.c_str(), tank.name().c_str() ); } else { //~ $1 - vehicle name, $2 - part name add_msg( m_good, _( "You purify the contents of the %1$s's %2$s" ), veh->name.c_str(), tank.name().c_str() ); veh->discharge_battery( tank.ammo_remaining() * cost ); tank.ammo_set( "water_clean", tank.ammo_remaining() ); } } return DONE; } case UNLOAD_TURRET: { g->unload( *turret.base() ); return DONE; } case RELOAD_TURRET: { item::reload_option opt = g->u.select_ammo( *turret.base(), true ); if( opt ) { g->u.assign_activity( activity_id( "ACT_RELOAD" ), opt.moves(), opt.qty() ); g->u.activity.targets.emplace_back( turret.base() ); g->u.activity.targets.push_back( std::move( opt.ammo ) ); } return DONE; } case FOLD_VEHICLE: veh->fold_up(); return DONE; case CONTROL: veh->use_controls( pos ); return DONE; case CONTROL_ELECTRONICS: veh->control_electronics(); return DONE; case EXAMINE: g->exam_vehicle( *veh ); return DONE; case TRACK: veh->toggle_tracking( ); return DONE; case GET_ITEMS_ON_GROUND: return ITEMS_FROM_GROUND; case GET_ITEMS: return from_vehicle ? ITEMS_FROM_CARGO : ITEMS_FROM_GROUND; } return DONE; }