diff --git a/src/vehicle.h b/src/vehicle.h index 52617d94f9d34..784c36866c8a8 100644 --- a/src/vehicle.h +++ b/src/vehicle.h @@ -317,6 +317,8 @@ struct vehicle_part { /** Can a player or NPC use this part as a seat? */ bool is_seat() const; + /* if this is a carried part, what is the name of the carried vehicle */ + std::string carried_name() const; /*@}*/ public: diff --git a/src/vehicle_display.cpp b/src/vehicle_display.cpp index df9dab0e439c9..17bd39305aa2a 100644 --- a/src/vehicle_display.cpp +++ b/src/vehicle_display.cpp @@ -272,9 +272,8 @@ void vehicle::print_vparts_descs( const catacurses::window &win, int max_y, int new_lines += 1; } if( vp.has_flag( vehicle_part::carried_flag ) ) { - std::string carried_name = vp.carry_names.top(); possible_msg << string_format( " Part of a %s carried on a rack.\n", - carried_name.substr( vehicle_part::name_offset ) ); + vp.carried_name() ); new_lines += 1; } diff --git a/src/vehicle_part.cpp b/src/vehicle_part.cpp index 80fe685e7167f..c056316750d97 100644 --- a/src/vehicle_part.cpp +++ b/src/vehicle_part.cpp @@ -571,3 +571,11 @@ bool vehicle::assign_seat( vehicle_part &pt, const npc &who ) return true; } + +std::string vehicle_part::carried_name() const +{ + if( carry_names.empty() ) { + return std::string(); + } + return carry_names.top().substr( name_offset ); +} diff --git a/src/vehicle_use.cpp b/src/vehicle_use.cpp index 19f642fc0fadc..e58bbe99ec4a2 100644 --- a/src/vehicle_use.cpp +++ b/src/vehicle_use.cpp @@ -1718,25 +1718,50 @@ void vehicle::use_bike_rack( int part ) } // check if we're storing a vehicle on this rack - std::vector carried_parts; - std::vector carry_rack; + std::vector> carried_vehicles; + std::vector> carrying_racks; bool found_vehicle = false; - for( const auto &rack_parts : racks_parts ) { - for( auto rack_part : rack_parts ) { + bool full_rack = true; + for( const std::vector &rack_parts : racks_parts ) { + std::vector carried_parts; + std::vector carry_rack; + size_t carry_size = 0; + std::string cur_vehicle; + + const auto add_vehicle = []( std::vector &carried_parts, + std::vector> &carried_vehicles, + std::vector &carry_rack, + std::vector> &carrying_racks ) { + if( !carry_rack.empty() ) { + carrying_racks.emplace_back( carry_rack ); + carried_vehicles.emplace_back( carried_parts ); + carry_rack.clear(); + carried_parts.clear(); + } + }; + + for( const int &rack_part : rack_parts ) { // skip parts that aren't carrying anything if( !parts[ rack_part ].has_flag( vehicle_part::carrying_flag ) ) { + add_vehicle( carried_parts, carried_vehicles, carry_rack, carrying_racks ); + cur_vehicle.clear(); continue; } - for( int i = 0; i < 4; i++ ) { - point near_loc = parts[ rack_part ].mount + vehicles::cardinal_d[ i ]; + for( const point &mount_dir : vehicles::cardinal_d ) { + point near_loc = parts[ rack_part ].mount + mount_dir; std::vector near_parts = parts_at_relative( near_loc, true ); if( near_parts.empty() ) { continue; } if( parts[ near_parts[ 0 ] ].has_flag( vehicle_part::carried_flag ) ) { + carry_size += 1; found_vehicle = true; // found a carried vehicle part - for( auto carried_part : near_parts ) { + if( parts[ near_parts[ 0 ] ].carried_name() != cur_vehicle ) { + add_vehicle( carried_parts, carried_vehicles, carry_rack, carrying_racks ); + cur_vehicle = parts[ near_parts[ 0 ] ].carried_name(); + } + for( const int &carried_part : near_parts ) { carried_parts.push_back( carried_part ); } carry_rack.push_back( rack_part ); @@ -1745,15 +1770,27 @@ void vehicle::use_bike_rack( int part ) } } } - if( found_vehicle ) { - break; - } + + add_vehicle( carried_parts, carried_vehicles, carry_rack, carrying_racks ); + full_rack &= carry_size == rack_parts.size(); } + int unload_carried = full_rack ? 0 : -1; bool success = false; - if( found_vehicle ) { - success = remove_carried_vehicle( carried_parts ); + if( found_vehicle && !full_rack ) { + uilist rack_menu; + rack_menu.addentry( 0, true, '0', _( "Load a vehicle on the rack" ) ); + for( size_t i = 0; i < carried_vehicles.size(); i++ ) { + rack_menu.addentry( i + 1, true, '1' + i, + string_format( _( "Remove the %s from the rack" ), + parts[ carried_vehicles[i].front() ].carried_name() ) ); + } + rack_menu.query(); + unload_carried = rack_menu.ret - 1; + } + if( unload_carried > -1 ) { + success = remove_carried_vehicle( carried_vehicles[unload_carried] ); if( success ) { - for( auto rack_part : carry_rack ) { + for( const int &rack_part : carrying_racks[unload_carried] ) { parts[ rack_part ].remove_flag( vehicle_part::carrying_flag ); } }