From dc6881b57d70a48490d6379d0237e6ad15848903 Mon Sep 17 00:00:00 2001 From: irwiss Date: Mon, 10 Jul 2023 16:21:21 +0300 Subject: [PATCH] Remove vehicle::part_flag(...) --- src/map.cpp | 32 ++-- src/pathfinding.cpp | 3 +- src/veh_appliance.cpp | 2 +- src/veh_interact.cpp | 156 ++++++++++---------- src/vehicle.cpp | 320 +++++++++++++++++++--------------------- src/vehicle.h | 4 - src/vehicle_display.cpp | 9 +- src/vehicle_move.cpp | 31 ++-- src/vehicle_use.cpp | 20 ++- 9 files changed, 277 insertions(+), 300 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 831c86d34ff98..d6d41c80086b9 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -5222,20 +5222,22 @@ static bool process_map_items( map &here, item_stack &items, safe_reference( time_left ) + 1; //~ %1$d: Number of minutes remaining, %2$s: Name of the vehicle @@ -5274,7 +5274,7 @@ static void process_vehicle_items( vehicle &cur_veh, int part ) break; } } - if( autoclave_finished && !cur_veh.part_flag( part, VPFLAG_APPLIANCE ) ) { + if( autoclave_finished && !vpi.has_flag( VPFLAG_APPLIANCE ) ) { add_msg( _( "The autoclave in the %s has finished its cycle." ), cur_veh.name ); } else if( autoclave_finished ) { add_msg( _( "The autoclave has finished its cycle." ) ); @@ -5283,8 +5283,8 @@ static void process_vehicle_items( vehicle &cur_veh, int part ) const int recharge_part_idx = cur_veh.part_with_feature( part, VPFLAG_RECHARGE, true ); if( recharge_part_idx >= 0 ) { - vehicle_part recharge_part = cur_veh.part( recharge_part_idx ); - if( !recharge_part.removed && !recharge_part.is_broken() && recharge_part.enabled ) { + const vehicle_part &recharge_part = cur_veh.part( recharge_part_idx ); + if( !recharge_part.removed && recharge_part.enabled ) { for( item &n : cur_veh.get_items( part ) ) { if( !n.has_flag( flag_RECHARGE ) && !n.has_flag( flag_USE_UPS ) ) { continue; diff --git a/src/pathfinding.cpp b/src/pathfinding.cpp index a08ed126ec730..1d14f37d485b6 100644 --- a/src/pathfinding.cpp +++ b/src/pathfinding.cpp @@ -351,7 +351,8 @@ std::vector map::route( const tripoint &f, const tripoint &t, newg += 2 * hp / bash + 8 + 4; } else if( part >= 0 ) { - if( !doors || !veh->part_flag( part, VPFLAG_OPENABLE ) ) { + const vehicle_part &vp = veh->part( part ); + if( !doors || !vp.info().has_flag( VPFLAG_OPENABLE ) ) { // Won't be openable, don't try from other sides layer.state[index] = ASL_CLOSED; } diff --git a/src/veh_appliance.cpp b/src/veh_appliance.cpp index d919373f92102..a8dcc58f761c1 100644 --- a/src/veh_appliance.cpp +++ b/src/veh_appliance.cpp @@ -354,7 +354,7 @@ bool veh_app_interact::can_unplug() { vehicle_part_range vpr = veh->get_all_parts(); return std::any_of( vpr.begin(), vpr.end(), []( const vpart_reference & ref ) { - return ref.vehicle().part_flag( static_cast( ref.part_index() ), "POWER_TRANSFER" ); + return ref.info().has_flag( "POWER_TRANSFER" ); } ); } diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index ff54a6c9334f6..bac9b0e242a33 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -844,10 +844,11 @@ bool veh_interact::update_part_requirements() int dif_steering = 0; if( sel_vpart_info->has_flag( "STEERABLE" ) ) { std::set axles; - for( int &p : veh->steering ) { - if( !veh->part_flag( p, "TRACKED" ) ) { + for( const int p : veh->steering ) { + const vehicle_part &vp = veh->part( p ); + if( !vp.info().has_flag( "TRACKED" ) ) { // tracked parts don't contribute to axle complexity - axles.insert( veh->part( p ).mount.x ); + axles.insert( vp.mount.x ); } } @@ -3096,12 +3097,16 @@ void act_vehicle_unload_fuel( vehicle *veh ) void veh_interact::complete_vehicle( Character &you ) { if( you.activity.values.size() < 7 ) { - debugmsg( "Invalid activity ACT_VEHICLE values:%d", you.activity.values.size() ); + debugmsg( "ACT_VEHICLE values.size() is %d", you.activity.values.size() ); + return; + } + if( you.activity.str_values.empty() ) { + debugmsg( "ACT_VEHICLE str_values is empty" ); return; } map &here = get_map(); - optional_vpart_position vp = here.veh_at( here.getlocal( tripoint( you.activity.values[0], - you.activity.values[1], you.posz() ) ) ); + const tripoint_abs_ms act_pos( you.activity.values[0], you.activity.values[1], you.posz() ); + optional_vpart_position vp = here.veh_at( act_pos ); if( !vp ) { // so the vehicle could have lost some of its parts from other NPCS works // during this player/NPCs activity. @@ -3118,24 +3123,19 @@ void veh_interact::complete_vehicle( Character &you ) return; } } - vehicle *const veh = &vp->vehicle(); - point d( you.activity.values[4], you.activity.values[5] ); - int vehicle_part = you.activity.values[6]; - cata_assert( !you.activity.str_values.empty() ); + vehicle &veh = vp->vehicle(); + const point d( you.activity.values[4], you.activity.values[5] ); const vpart_id part_id( you.activity.str_values[0] ); - const vpart_info &vpinfo = part_id.obj(); // cmd = Install Repair reFill remOve Siphon Unload reName relAbel switch( static_cast( you.activity.index ) ) { case 'i': { const inventory &inv = you.crafting_inventory(); - const requirement_data reqs = vpinfo.install_requirements(); if( !reqs.can_make_with_inventory( inv, is_crafting_component ) ) { - add_msg( m_info, _( "You don't meet the requirements to install the %s." ), - vpinfo.name() ); + add_msg( m_info, _( "You don't meet the requirements to install the %s." ), vpinfo.name() ); break; } @@ -3152,8 +3152,7 @@ void veh_interact::complete_vehicle( Character &you ) } if( base.is_null() ) { if( !you.has_trait( trait_DEBUG_HS ) ) { - add_msg( m_info, _( "Could not find base part in requirements for %s." ), - vpinfo.name() ); + add_msg( m_info, _( "Could not find base part in requirements for %s." ), vpinfo.name() ); break; } else { base = item( vpinfo.base_item ); @@ -3165,47 +3164,46 @@ void veh_interact::complete_vehicle( Character &you ) } you.invalidate_crafting_inventory(); - cata_assert( you.activity.str_values.size() >= 2 ); - const int partnum = veh->install_part( d, part_id, std::move( base ) ); + const int partnum = veh.install_part( d, part_id, std::move( base ) ); if( partnum < 0 ) { debugmsg( "complete_vehicle install part fails dx=%d dy=%d id=%s", d.x, d.y, part_id.c_str() ); break; } - ::vehicle_part &vp_new = veh->part( partnum ); + ::vehicle_part &vp_new = veh.part( partnum ); if( vp_new.info().variants.size() > 1 ) { do_change_shape_menu( vp_new ); } // Need map-relative coordinates to compare to output of look_around. // Need to call coord_translate() directly since it's a new part. - const point q = veh->coord_translate( d ); + const point q = veh.coord_translate( d ); if( vpinfo.has_flag( VPFLAG_CONE_LIGHT ) || vpinfo.has_flag( VPFLAG_WIDE_CONE_LIGHT ) || vpinfo.has_flag( VPFLAG_HALF_CIRCLE_LIGHT ) ) { - orient_part( veh, vpinfo, partnum, q ); + orient_part( &veh, vpinfo, partnum, q ); } - const tripoint vehp = veh->global_pos3() + tripoint( q, 0 ); + const tripoint vehp = veh.global_pos3() + tripoint( q, 0 ); // TODO: allow boarding for non-players as well. Character *const pl = get_creature_tracker().creature_at( vehp ); if( vpinfo.has_flag( VPFLAG_BOARDABLE ) && pl ) { here.board_vehicle( vehp, pl ); } - you.add_msg_if_player( m_good, _( "You install a %1$s into the %2$s." ), - vp_new.name(), veh->name ); + you.add_msg_if_player( m_good, _( "You install a %1$s into the %2$s." ), vp_new.name(), veh.name ); for( const auto &sk : vpinfo.install_skills ) { you.practice( sk.first, veh_utils::calc_xp_gain( vpinfo, sk.first, you ) ); } - here.add_vehicle_to_cache( veh ); + here.add_vehicle_to_cache( &veh ); break; } case 'r': { - veh_utils::repair_part( *veh, veh->part( vehicle_part ), you ); + vehicle_part &vp = veh.part( you.activity.values[6] ); + veh_utils::repair_part( veh, vp, you ); break; } @@ -3216,25 +3214,23 @@ void veh_interact::complete_vehicle( Character &you ) } item_location &src = you.activity.targets.front(); - struct vehicle_part &pt = veh->part( vehicle_part ); - if( pt.is_tank() && src->is_container() && !src->empty() ) { + vehicle_part &vp = veh.part( you.activity.values[6] ); + if( vp.is_tank() && src->is_container() && !src->empty() ) { item_location contained( src, &src->only_item() ); - contained->charges -= pt.base.fill_with( *contained, contained->charges ); + contained->charges -= vp.base.fill_with( *contained, contained->charges ); contents_change_handler handler; handler.unseal_pocket_containing( contained ); - // if code goes here, we can assume "pt" has already refilled with "contained" something. - int remaining_ammo_capacity = pt.ammo_capacity( contained->ammo_type() ) - pt.ammo_remaining(); + // if code goes here, we can assume "vp" has already refilled with "contained" something. + int remaining_ammo_capacity = vp.ammo_capacity( contained->ammo_type() ) - vp.ammo_remaining(); if( remaining_ammo_capacity ) { //~ 1$s vehicle name, 2$s tank name - you.add_msg_if_player( m_good, _( "You refill the %1$s's %2$s." ), - veh->name, pt.name() ); + you.add_msg_if_player( m_good, _( "You refill the %1$s's %2$s." ), veh.name, vp.name() ); } else { //~ 1$s vehicle name, 2$s tank name - you.add_msg_if_player( m_good, _( "You completely refill the %1$s's %2$s." ), - veh->name, pt.name() ); + you.add_msg_if_player( m_good, _( "You completely refill the %1$s's %2$s." ), veh.name, vp.name() ); } if( contained->charges == 0 ) { @@ -3244,16 +3240,15 @@ void veh_interact::complete_vehicle( Character &you ) } handler.handle_by( you ); - } else if( pt.is_fuel_store() ) { + } else if( vp.is_fuel_store() ) { contents_change_handler handler; handler.unseal_pocket_containing( src ); int qty = src->charges; - pt.base.reload( you, std::move( src ), qty ); + vp.base.reload( you, std::move( src ), qty ); //~ 1$s vehicle name, 2$s reactor name - you.add_msg_if_player( m_good, _( "You refuel the %1$s's %2$s." ), - veh->name, pt.name() ); + you.add_msg_if_player( m_good, _( "You refuel the %1$s's %2$s." ), veh.name, vp.name() ); handler.handle_by( you ); } else { @@ -3261,19 +3256,16 @@ void veh_interact::complete_vehicle( Character &you ) break; } - veh->invalidate_mass(); + veh.invalidate_mass(); break; } case 'O': // 'O' = remove appliance case 'o': { - const bool appliance_removal = static_cast( you.activity.index ) == 'O'; - const bool wall_wire_removal = appliance_removal && - veh->part( vehicle_part ).info().id == vpart_ap_wall_wiring; - const inventory &inv = you.crafting_inventory(); - if( vehicle_part >= veh->part_count() ) { - vehicle_part = veh->get_next_shifted_index( vehicle_part, you ); - if( vehicle_part == -1 ) { + int vp_index = you.activity.values[6]; + if( vp_index >= veh.part_count() ) { + vp_index = veh.get_next_shifted_index( vp_index, you ); + if( vp_index == -1 ) { you.add_msg_if_player( m_info, //~ 1$s is the vehicle part name _( "The %1$s has already been removed by someone else." ), @@ -3281,11 +3273,17 @@ void veh_interact::complete_vehicle( Character &you ) return; } } - const requirement_data reqs = vpinfo.removal_requirements(); + const vehicle_part &vp = veh.part( vp_index ); + const vpart_info &vpi = vp.info(); + const bool appliance_removal = static_cast( you.activity.index ) == 'O'; + const bool wall_wire_removal = appliance_removal && vpi.id == vpart_ap_wall_wiring; + const bool broken = vp.is_broken(); + const bool smash_remove = vpi.has_flag( "SMASH_REMOVE" ); + const inventory &inv = you.crafting_inventory(); + const requirement_data &reqs = vpi.removal_requirements(); if( !reqs.can_make_with_inventory( inv, is_crafting_component ) ) { //~ 1$s is the vehicle part name - add_msg( m_info, _( "You don't meet the requirements to remove the %1$s." ), - vpinfo.name() ); + add_msg( m_info, _( "You don't meet the requirements to remove the %1$s." ), vpi.name() ); break; } for( const auto &e : reqs.get_components() ) { @@ -3301,70 +3299,64 @@ void veh_interact::complete_vehicle( Character &you ) std::list resulting_items; // First we get all the contents of the part - vehicle_stack contents = veh->get_items( vehicle_part ); + vehicle_stack contents = veh.get_items( vp_index ); resulting_items.insert( resulting_items.end(), contents.begin(), contents.end() ); contents.clear(); // Power cables must remove parts from the target vehicle, too. - if( veh->part_flag( vehicle_part, "POWER_TRANSFER" ) ) { - veh->remove_remote_part( vehicle_part ); + if( vpi.has_flag( "POWER_TRANSFER" ) ) { + veh.remove_remote_part( vp_index ); } - bool broken = veh->part( vehicle_part ).is_broken(); - bool smash_remove = veh->part( vehicle_part ).info().has_flag( "SMASH_REMOVE" ); - if( broken ) { - you.add_msg_if_player( _( "You remove the broken %1$s from the %2$s." ), - veh->part( vehicle_part ).name(), veh->name ); + you.add_msg_if_player( _( "You remove the broken %1$s from the %2$s." ), vp.name(), veh.name ); } else if( smash_remove ) { you.add_msg_if_player( _( "You smash the %1$s to bits, removing it from the %2$s." ), - veh->part( vehicle_part ).name(), veh->name ); + vp.name(), veh.name ); } else { - you.add_msg_if_player( _( "You remove the %1$s from the %2$s." ), - veh->part( vehicle_part ).name(), veh->name ); + you.add_msg_if_player( _( "You remove the %1$s from the %2$s." ), vp.name(), veh.name ); } if( wall_wire_removal ) { - veh->part( vehicle_part ).properties_to_item(); - } else if( veh->part_flag( vehicle_part, "TOW_CABLE" ) ) { - veh->invalidate_towing( true, &you ); + vp.properties_to_item(); // what's going on here? this line isn't doing anything... + } else if( vpi.has_flag( "TOW_CABLE" ) ) { + veh.invalidate_towing( true, &you ); } else if( broken ) { - item_group::ItemList pieces = veh->part( vehicle_part ).pieces_for_broken_part(); + item_group::ItemList pieces = vp.pieces_for_broken_part(); resulting_items.insert( resulting_items.end(), pieces.begin(), pieces.end() ); } else { if( smash_remove ) { - item_group::ItemList pieces = veh->part( vehicle_part ).pieces_for_broken_part(); + item_group::ItemList pieces = vp.pieces_for_broken_part(); resulting_items.insert( resulting_items.end(), pieces.begin(), pieces.end() ); } else { - resulting_items.push_back( veh->part( vehicle_part ).properties_to_item() ); + resulting_items.push_back( vp.properties_to_item() ); } - for( const std::pair &sk : vpinfo.install_skills ) { + for( const std::pair &sk : vpi.install_skills ) { // removal is half as educational as installation - you.practice( sk.first, veh_utils::calc_xp_gain( vpinfo, sk.first, you ) / 2 ); + you.practice( sk.first, veh_utils::calc_xp_gain( vpi, sk.first, you ) / 2 ); } } // Remove any leftover power cords from the appliance - if( appliance_removal && veh->part_count() >= 2 ) { - veh->shed_loose_parts(); - veh->part_removal_cleanup(); + if( appliance_removal && veh.part_count() >= 2 ) { + veh.shed_loose_parts(); + veh.part_removal_cleanup(); //always stop after removing an appliance you.activity.set_to_null(); } - if( veh->part_count_real() <= 1 ) { - you.add_msg_if_player( _( "You completely dismantle the %s." ), veh->name ); + if( veh.part_count_real() <= 1 ) { + you.add_msg_if_player( _( "You completely dismantle the %s." ), veh.name ); you.activity.set_to_null(); // destroy vehicle clears the cache - here.destroy_vehicle( veh ); + here.destroy_vehicle( &veh ); } else { - point mount = veh->part( vehicle_part ).mount; - const tripoint part_pos = veh->global_part_pos3( vehicle_part ); - veh->remove_part( vehicle_part ); + const tripoint part_pos = veh.global_part_pos3( vp ); + veh.remove_part( vp_index ); // part_removal_cleanup calls refresh, so parts_at_relative is valid - veh->part_removal_cleanup(); - if( veh->parts_at_relative( mount, true ).empty() ) { - get_map().clear_vehicle_point_from_cache( veh, part_pos ); + veh.part_removal_cleanup(); + if( veh.parts_at_relative( vp.mount, true ).empty() ) { + get_map().clear_vehicle_point_from_cache( &veh, part_pos ); } } // This will be part of an NPC "job" where they need to clean up the activity @@ -3384,7 +3376,7 @@ void veh_interact::complete_vehicle( Character &you ) // Unplug action just sheds loose connections, // assuming vehicle::shed_loose_parts was already called so that // the removed parts have had time to be processed - you.add_msg_if_player( _( "You disconnect the %s's power connection." ), veh->name ); + you.add_msg_if_player( _( "You disconnect the %s's power connection." ), veh.name ); break; } } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 1c40c2c52bd25..c8d33e5ab7527 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -174,9 +174,11 @@ void vehicle_stack::insert( const item &newitem ) units::volume vehicle_stack::max_volume() const { - if( myorigin->part_flag( part_num, "CARGO" ) && !myorigin->part( part_num ).is_broken() ) { + const vehicle_part &vp = myorigin->part( part_num ); + const vpart_info &vpi = vp.info(); + if( vpi.has_flag( VPFLAG_CARGO ) && !vp.is_broken() ) { // Set max volume for vehicle cargo to prevent integer overflow - return std::min( myorigin->part( part_num ).info().size, 10000_liter ); + return std::min( vpi.size, 10000_liter ); } return 0_ml; } @@ -996,16 +998,15 @@ bool vehicle::is_alternator_on( const vehicle_part &vp ) const bool vehicle::has_security_working() const { - bool found_security = false; if( fuel_left( fuel_type_battery ) > 0 ) { - for( int s : speciality ) { - if( part_flag( s, "SECURITY" ) && parts[ s ].is_available() ) { - found_security = true; - break; + for( const int s : speciality ) { + const vehicle_part &vp = part( s ); + if( vp.info().has_flag( "SECURITY" ) && vp.is_available() ) { + return true; } } } - return found_security; + return false; } void vehicle::unlock() @@ -1838,7 +1839,7 @@ bool vehicle::remove_part( const int p, RemovePartHandler &handler ) if( !handler.get_map_ref().inbounds( part_loc ) ) { debugmsg( "vehicle::remove_part part '%s' at mount %s bub pos %s is out of map " "bounds on vehicle '%s'(%s), vehicle::pos is %s, vehicle::sm_pos is %s", - vp.info().id.str(), vp.mount.to_string(), part_loc.to_string(), + vpi.id.str(), vp.mount.to_string(), part_loc.to_string(), name, type.str(), pos.to_string(), sm_pos.to_string() ); } @@ -1867,11 +1868,11 @@ bool vehicle::remove_part( const int p, RemovePartHandler &handler ) // if a windshield is removed (usually destroyed) also remove curtains // attached to it. - if( remove_dependent_part( "WINDOW", "CURTAIN" ) || part_flag( p, VPFLAG_OPAQUE ) ) { + if( remove_dependent_part( "WINDOW", "CURTAIN" ) || vpi.has_flag( VPFLAG_OPAQUE ) ) { handler.set_transparency_cache_dirty( sm_pos.z ); } - if( part_flag( p, VPFLAG_ROOF ) || part_flag( p, VPFLAG_OPAQUE ) ) { + if( vpi.has_flag( VPFLAG_ROOF ) || vpi.has_flag( VPFLAG_OPAQUE ) ) { handler.set_floor_cache_dirty( sm_pos.z + 1 ); } @@ -1880,20 +1881,20 @@ bool vehicle::remove_part( const int p, RemovePartHandler &handler ) remove_dependent_part( "HANDHELD_BATTERY_MOUNT", "NEEDS_HANDHELD_BATTERY_MOUNT" ); // Release any animal held by the part - if( parts[p].has_flag( vp_flag::animal_flag ) ) { - item base = parts[p].get_base(); + if( vp.has_flag( vp_flag::animal_flag ) ) { + item base = vp.get_base(); handler.spawn_animal_from_part( base, part_loc ); - parts[p].set_base( std::move( base ) ); - parts[p].remove_flag( vp_flag::animal_flag ); + vp.set_base( std::move( base ) ); + vp.remove_flag( vp_flag::animal_flag ); } // Update current engine configuration if needed - if( part_flag( p, "ENGINE" ) && engines.size() > 1 ) { + if( vpi.has_flag( VPFLAG_ENGINE ) && engines.size() > 1 ) { bool any_engine_on = false; for( const int e : engines ) { - const vehicle_part &vp = parts[e]; - if( e != p && vp.enabled ) { + const vehicle_part &vp_engine = parts[e]; + if( &vp != &vp_engine && vp_engine.enabled ) { any_engine_on = true; break; } @@ -1901,31 +1902,31 @@ bool vehicle::remove_part( const int p, RemovePartHandler &handler ) if( !any_engine_on ) { engine_on = false; - for( const int p : engines ) { - vehicle_part &vp = parts[p]; - vp.enabled = true; + for( const int e : engines ) { + vehicle_part &vp_engine = parts[e]; + vp_engine.enabled = true; } } } //Remove loot zone if Cargo was removed. - const auto lz_iter = loot_zones.find( parts[p].mount ); + const auto lz_iter = loot_zones.find( vp.mount ); const bool no_zone = lz_iter != loot_zones.end(); - if( no_zone && part_flag( p, "CARGO" ) ) { + if( no_zone && vpi.has_flag( VPFLAG_CARGO ) ) { // Using the key here (instead of the iterator) will remove all zones on // this mount points regardless of how many there are - loot_zones.erase( parts[p].mount ); + loot_zones.erase( vp.mount ); zones_dirty = true; } - parts[p].removed = true; - if( parts[p].has_fake && parts[p].fake_part_at < static_cast( parts.size() ) ) { - parts[parts[p].fake_part_at].removed = true; + vp.removed = true; + if( vp.has_fake && vp.fake_part_at < static_cast( parts.size() ) ) { + parts[vp.fake_part_at].removed = true; } handler.removed( *this, p ); - const point &vp_mount = parts[p].mount; + const point &vp_mount = vp.mount; const auto iter = labels.find( label( vp_mount ) ); if( iter != labels.end() && parts_at_relative( vp_mount, false ).empty() ) { labels.erase( iter ); @@ -2277,8 +2278,10 @@ bool vehicle::split_vehicles( map &here, std::vector passengers; for( size_t new_part = 0; new_part < split_parts.size(); new_part++ ) { - int mov_part = split_parts[ new_part ]; - point cur_mount = parts[ mov_part ].mount; + const int mov_part = split_parts[ new_part ]; + vehicle_part &vp_mov = part( mov_part ); + const vpart_info &vpi_mov = vp_mov.info(); + point cur_mount = vp_mov.mount; point new_mount = cur_mount; if( !split_mounts.empty() ) { new_mount = split_mounts[ new_part ]; @@ -2288,14 +2291,14 @@ bool vehicle::split_vehicles( map &here, Character *passenger = nullptr; // Unboard any entities standing on any transferred part - if( part_flag( mov_part, "BOARDABLE" ) ) { + if( vpi_mov.has_flag( VPFLAG_BOARDABLE ) ) { passenger = get_passenger( mov_part ); if( passenger ) { passengers.push_back( passenger ); } } // if this part is a towing part, transfer the tow_data to the new vehicle. - if( part_flag( mov_part, "TOW_CABLE" ) ) { + if( vpi_mov.has_flag( "TOW_CABLE" ) ) { if( is_towed() ) { tow_data.get_towed_by()->tow_data.set_towing( tow_data.get_towed_by(), new_vehicle ); tow_data.clear_towing(); @@ -2305,7 +2308,7 @@ bool vehicle::split_vehicles( map &here, } } // transfer the vehicle_part to the new vehicle - new_vehicle->parts.emplace_back( parts[ mov_part ] ); + new_vehicle->parts.emplace_back( vp_mov ); new_vehicle->parts.back().mount = new_mount; // remove labels associated with the mov_part @@ -2331,11 +2334,11 @@ bool vehicle::split_vehicles( map &here, // remove the passenger from the old vehicle if( passenger ) { - parts[ mov_part ].remove_flag( vp_flag::passenger_flag ); - parts[ mov_part ].passenger_id = character_id(); + vp_mov.remove_flag( vp_flag::passenger_flag ); + vp_mov.passenger_id = character_id(); } // indicate the part needs to be removed from the old vehicle - parts[ mov_part].removed = true; + vp_mov.removed = true; } // We want to create the vehicle zones after we've setup the parts @@ -2729,11 +2732,10 @@ int vehicle::next_part_to_close( int p, bool outside ) const for( std::vector::reverse_iterator part_it = parts_here.rbegin(); part_it != parts_here.rend(); ++part_it ) { - - if( part_flag( *part_it, VPFLAG_OPENABLE ) - && parts[ *part_it ].is_available() - && parts[*part_it].open == 1 - && ( !outside || !part_flag( *part_it, "OPENCLOSE_INSIDE" ) ) ) { + const vehicle_part &vp = part( *part_it ); + const vpart_info &vpi = vp.info(); + if( vpi.has_flag( VPFLAG_OPENABLE ) && vp.is_available() && vp.open == 1 + && ( !outside || !vpi.has_flag( "OPENCLOSE_INSIDE" ) ) ) { return *part_it; } } @@ -2742,15 +2744,15 @@ int vehicle::next_part_to_close( int p, bool outside ) const int vehicle::next_part_to_open( int p, bool outside ) const { - - const std::vector parts_here = parts_at_relative( parts[p].mount, true, true ); const bool has_lock = part_has_lock( p ); // We want forwards, since we open the outermost thing first (curtains), and then the innermost thing (door) - for( const int &elem : parts_here ) { - if( part_flag( elem, VPFLAG_OPENABLE ) && parts[ elem ].is_available() && parts[elem].open == 0 && - !( part( elem ).locked && has_lock ) && - ( !outside || !part_flag( elem, "OPENCLOSE_INSIDE" ) ) ) { + for( const int elem : parts_at_relative( parts[p].mount, true, true ) ) { + const vehicle_part &vp = part( elem ); + const vpart_info &vpi = vp.info(); + if( vpi.has_flag( VPFLAG_OPENABLE ) && vp.is_available() && vp.open == 0 && + !( vp.locked && has_lock ) && + ( !outside || !vpi.has_flag( "OPENCLOSE_INSIDE" ) ) ) { return elem; } } @@ -2759,9 +2761,9 @@ int vehicle::next_part_to_open( int p, bool outside ) const bool vehicle::part_has_lock( int p ) const { - const std::vector parts_here = parts_at_relative( parts[p].mount, true, true ); - for( const int &elem : parts_here ) { - if( part_flag( elem, "DOOR_LOCKING" ) && parts[elem].is_available() ) { + for( const int elem : parts_at_relative( parts[p].mount, true, true ) ) { + const vehicle_part &vp = parts[elem]; + if( vp.info().has_flag( "DOOR_LOCKING" ) && vp.is_available() ) { return true; } } @@ -2770,17 +2772,17 @@ bool vehicle::part_has_lock( int p ) const int vehicle::next_part_to_lock( int p, bool outside ) const { - std::vector parts_here = parts_at_relative( parts[p].mount, true, true ); if( !part_has_lock( p ) ) { return -1; } + std::vector parts_here = parts_at_relative( parts[p].mount, true, true ); // We want reverse, since we lock the innermost thing first (door), and then the outermost thing for( std::vector::reverse_iterator part_it = parts_here.rbegin(); part_it != parts_here.rend(); ++part_it ) { - - if( part_flag( *part_it, "LOCKABLE_DOOR" ) && parts[*part_it].is_available() && - parts[*part_it].open == 0 && !part( *part_it ).locked && !outside ) { + const vehicle_part &vp = part( *part_it ); + if( vp.info().has_flag( "LOCKABLE_DOOR" ) && vp.is_available() && + vp.open == 0 && !vp.locked && !outside ) { return *part_it; } } @@ -2789,13 +2791,12 @@ int vehicle::next_part_to_lock( int p, bool outside ) const int vehicle::next_part_to_unlock( int p, bool outside ) const { - const std::vector parts_here = parts_at_relative( parts[p].mount, true, true ); if( !part_has_lock( p ) ) { return -1; } - for( const int &elem : parts_here ) { - if( part_flag( elem, "LOCKABLE_DOOR" ) && parts[elem].is_available() && - part( elem ).locked && !outside ) { + for( const int elem : parts_at_relative( parts[p].mount, true, true ) ) { + const vehicle_part &vp = part( elem ); + if( vp.info().has_flag( "LOCKABLE_DOOR" ) && vp.is_available() && vp.locked && !outside ) { return elem; } } @@ -3006,24 +3007,6 @@ std::vector> vehicle::find_lines_of_parts( return ret_parts; } -bool vehicle::part_flag( int part, const std::string &flag ) const -{ - if( part < 0 || part >= static_cast( parts.size() ) || parts[part].removed ) { - return false; - } else { - return part_info( part ).has_flag( flag ); - } -} - -bool vehicle::part_flag( int part, const vpart_bitflags flag ) const -{ - if( part < 0 || part >= static_cast( parts.size() ) || parts[part].removed ) { - return false; - } else { - return part_info( part ).has_flag( flag ); - } -} - int vehicle::part_at( const point &dp ) const { for( const vpart_reference &vp : get_all_parts() ) { @@ -3102,13 +3085,12 @@ int vehicle::part_displayed_at( const point &dp, bool include_fake, bool below_r int vehicle::roof_at_part( const int part ) const { - std::vector parts_in_square = parts_at_relative( parts[part].mount, true ); - for( const int p : parts_in_square ) { - if( part_info( p ).location == "on_roof" || part_flag( p, "ROOF" ) ) { + for( const int p : parts_at_relative( parts[part].mount, true ) ) { + const vehicle_part &vp = parts[p]; + if( vp.info().location == "on_roof" || vp.info().has_flag( VPFLAG_ROOF ) ) { return p; } } - return -1; } @@ -6664,16 +6646,13 @@ bool vehicle::no_towing_slack() const void vehicle::remove_remote_part( int part_num ) { vehicle *veh = find_vehicle( parts[part_num].target.second ); - // If the target vehicle is still there, ask it to remove its part if( veh != nullptr ) { const tripoint local_abs = get_map().getabs( global_part_pos3( part_num ) ); - for( size_t j = 0; j < veh->loose_parts.size(); j++ ) { - int remote_partnum = veh->loose_parts[j]; - const vehicle_part *remote_part = &veh->parts[remote_partnum]; - - if( veh->part_flag( remote_partnum, "POWER_TRANSFER" ) && remote_part->target.first == local_abs ) { + const int remote_partnum = veh->loose_parts[j]; + const vehicle_part &vp_remote = veh->parts[remote_partnum]; + if( vp_remote.info().has_flag( "POWER_TRANSFER" ) && vp_remote.target.first == local_abs ) { veh->remove_part( remote_partnum ); return; } @@ -6687,40 +6666,42 @@ void vehicle::shed_loose_parts( const tripoint_bub_ms *src, const tripoint_bub_m // remove_part rebuilds the loose_parts vector, so iterate over a copy to preserve // power transfer lines that still have some slack to them std::vector lp = loose_parts; - for( const int &elem : lp ) { + for( const int elem : lp ) { + vehicle_part &vp_loose = part( elem ); if( std::find( loose_parts.begin(), loose_parts.end(), elem ) == loose_parts.end() ) { // part was removed elsewhere continue; } - if( part_flag( elem, "POWER_TRANSFER" ) ) { - int distance = rl_dist( here.getabs( bub_part_pos( parts[elem] ) ), parts[elem].target.second ); - int max_dist = parts[elem].get_base().type->maximum_charges(); + if( vp_loose.info().has_flag( "POWER_TRANSFER" ) ) { + int distance = rl_dist( here.getabs( bub_part_pos( vp_loose ) ), vp_loose.target.second ); + int max_dist = vp_loose.get_base().type->maximum_charges(); if( src && ( max_dist - distance ) > 0 ) { // power line still has some slack to it, so keep it attached for now - vehicle *veh = find_vehicle( parts[elem].target.second ); + vehicle *veh = find_vehicle( vp_loose.target.second ); if( veh != nullptr ) { for( int remote_lp : veh->loose_parts ) { - if( veh->part_flag( remote_lp, "POWER_TRANSFER" ) && - veh->parts[remote_lp].target.first == here.getabs( *src ) ) { + vehicle_part &vp_remote = veh->part( remote_lp ); + if( vp_remote.info().has_flag( "POWER_TRANSFER" ) && + vp_remote.target.first == here.getabs( *src ) ) { // update remote part's target to new position - veh->parts[remote_lp].target.first = here.getabs( dst ? *dst : bub_part_pos( elem ) ); - veh->parts[remote_lp].target.second = veh->parts[remote_lp].target.first; + vp_remote.target.first = here.getabs( dst ? *dst : bub_part_pos( vp_loose ) ); + vp_remote.target.second = vp_remote.target.first; } } } continue; } - add_msg_if_player_sees( global_part_pos3( parts[elem] ), m_warning, + add_msg_if_player_sees( global_part_pos3( vp_loose ), m_warning, _( "The %s's power connection was detached!" ), name ); remove_remote_part( elem ); } - if( part_flag( elem, "TOW_CABLE" ) ) { + if( vp_loose.info().has_flag( "TOW_CABLE" ) ) { invalidate_towing( true ); continue; } - const item drop = part( elem ).properties_to_item(); + const item drop = vp_loose.properties_to_item(); if( !magic && !drop.has_flag( flag_AUTO_DELETE_CABLE ) ) { - here.add_item_or_charges( global_part_pos3( part( elem ) ), drop ); + here.add_item_or_charges( global_part_pos3( vp_loose ), drop ); } remove_part( elem ); @@ -6834,15 +6815,16 @@ int vehicle::damage( map &here, int p, int dmg, const damage_type_id &type, bool int target_part = vp_initial.info().rotor_diameter() ? p : random_entry( parts_here ); // Parts integrated inside a door or board are protected by boards and closed doors - if( part_flag( target_part, "BOARD_INTERNAL" ) ) { + if( part( target_part ).info().has_flag( "BOARD_INTERNAL" ) ) { int strongest_board_durability = INT_MIN; for( const int part : parts_here ) { - if( part_flag( part, "FULL_BOARD" ) || - part_flag( part, "HALF_BOARD" ) || - ( part_flag( part, "OPENABLE" ) && !parts[part].open ) ) { - if( part_info( part ).durability > strongest_board_durability ) { + const vehicle_part &vp_here = parts[part]; + const vpart_info &vpi_here = vp_here.info(); + if( vpi_here.has_flag( "FULL_BOARD" ) || vpi_here.has_flag( "HALF_BOARD" ) || + ( vpi_here.has_flag( "OPENABLE" ) && !vp_here.open ) ) { + if( vpi_here.durability > strongest_board_durability ) { target_part = part; - strongest_board_durability = part_info( part ).durability; + strongest_board_durability = vpi_here.durability; } } } @@ -6969,13 +6951,15 @@ bool vehicle::shift_if_needed( map &here ) int vehicle::break_off( map &here, int p, int dmg ) { + const vehicle_part &vp = parts[p]; + const vpart_info &vpi = vp.info(); /* Already-destroyed part - chance it could be torn off into pieces. * Chance increases with damage, and decreases with part max durability * (so lights, etc are easily removed; frames and plating not so much) */ - if( rng( 0, part_info( p ).durability / 10 ) >= dmg ) { + if( rng( 0, vpi.durability / 10 ) >= dmg ) { return dmg; } - const tripoint pos = global_part_pos3( p ); + const tripoint pos = global_part_pos3( vp ); const auto scatter_parts = [&]( const vehicle_part & pt ) { for( const item &piece : pt.pieces_for_broken_part() ) { // inside the loop, so each piece goes to a different place @@ -6995,80 +6979,75 @@ int vehicle::break_off( map &here, int p, int dmg ) } else { handler_ptr = std::make_unique( here ); } - if( part_info( p ).location == part_location_structure ) { + if( vpi.location == part_location_structure ) { // For structural parts, remove other parts first - std::vector parts_in_square = parts_at_relative( parts[p].mount, true ); + std::vector parts_in_square = parts_at_relative( vp.mount, true ); for( int index = parts_in_square.size() - 1; index >= 0; index-- ) { // Ignore the frame being destroyed if( parts_in_square[index] == p ) { continue; } + vehicle_part &vp_here = parts[parts_in_square[index]]; + const vpart_info &vpi_here = vp_here.info(); - if( part_flag( parts_in_square[ index ], "TOW_CABLE" ) ) { + if( vpi_here.has_flag( "TOW_CABLE" ) ) { // Tow cables - remove it in one piece, remove remote part, and remove towing data - add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, - parts[ parts_in_square[ index ] ].name() ); + add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, vp_here.name() ); invalidate_towing( true ); - } else if( part_flag( parts_in_square[ index ], "POWER_TRANSFER" ) ) { + } else if( vpi_here.has_flag( "POWER_TRANSFER" ) ) { // Electrical cables - remove it in one piece and remove remote part - add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, - parts[ parts_in_square[ index ] ].name() ); - item part_as_item = parts[parts_in_square[index]].properties_to_item(); - here.add_item_or_charges( pos, part_as_item ); + add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, vp_here.name() ); + here.add_item_or_charges( pos, vp_here.properties_to_item() ); remove_remote_part( parts_in_square[ index ] ); - } else if( parts[ parts_in_square[ index ] ].is_broken() ) { + } else if( vp_here.is_broken() ) { // Tearing off a broken part - break it up - add_msg_if_player_sees( pos, m_bad, _( "The %s's %s breaks into pieces!" ), name, - parts[ parts_in_square[ index ] ].name() ); - scatter_parts( parts[parts_in_square[index]] ); + add_msg_if_player_sees( pos, m_bad, _( "The %s's %s breaks into pieces!" ), name, vp_here.name() ); + scatter_parts( vp_here ); } else { // Intact (but possibly damaged) part - remove it in one piece - add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is torn off!" ), name, - parts[ parts_in_square[ index ] ].name() ); + add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is torn off!" ), name, vp_here.name() ); if( !magic ) { - item part_as_item = parts[parts_in_square[index]].properties_to_item(); - here.add_item_or_charges( pos, part_as_item ); + here.add_item_or_charges( pos, vp_here.properties_to_item() ); } } remove_part( parts_in_square[index], *handler_ptr ); } // After clearing the frame, remove it. - add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is destroyed!" ), name, parts[ p ].name() ); - scatter_parts( parts[p] ); + add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is destroyed!" ), name, vp.name() ); + scatter_parts( vp ); remove_part( p, *handler_ptr ); find_and_split_vehicles( here, { p } ); } else { - if( part_flag( p, "TOW_CABLE" ) ) { + if( vpi.has_flag( "TOW_CABLE" ) ) { // Tow cables - remove it in one piece, remove remote part, and remove towing data - add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, - parts[ p ].name() ); + add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, vp.name() ); invalidate_towing( true ); - } else if( part_flag( p, "POWER_TRANSFER" ) ) { + } else if( vpi.has_flag( "POWER_TRANSFER" ) ) { // Electrical cables - remove it in one piece and remove remote part - add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, - parts[ p ].name() ); - item part_as_item = parts[p].properties_to_item(); - here.add_item_or_charges( pos, part_as_item ); + add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, vp.name() ); + here.add_item_or_charges( pos, vp.properties_to_item() ); remove_remote_part( p ); } else { //Just break it off - add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is destroyed!" ), name, parts[ p ].name() ); - - scatter_parts( parts[p] ); + add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is destroyed!" ), name, vp.name() ); + scatter_parts( vp ); } - const point position = parts[p].mount; + const point position = vp.mount; remove_part( p, *handler_ptr ); // remove parts for which required flags are not present anymore - if( !part_info( p ).get_flags().empty() ) { + if( !vpi.get_flags().empty() ) { const std::vector parts_here = parts_at_relative( position, false ); - for( const int &part : parts_here ) { + for( const int part : parts_here ) { + vehicle_part &vp_here = parts[part]; + const vpart_info &vpi_here = vp_here.info(); bool remove = false; - for( const std::string &flag : part_info( part ).get_flags() ) { - if( !json_flag::get( flag ).requires_flag().empty() ) { + for( const std::string &flag : vpi_here.get_flags() ) { + const std::string &required_flag = json_flag::get( flag ).requires_flag(); + if( !required_flag.empty() ) { remove = true; - for( const int &elem : parts_here ) { - if( part_info( elem ).has_flag( json_flag::get( flag ).requires_flag() ) ) { + for( const int elem : parts_here ) { + if( parts[elem].info().has_flag( required_flag ) ) { remove = false; continue; } @@ -7076,14 +7055,13 @@ int vehicle::break_off( map &here, int p, int dmg ) } } if( remove ) { - if( part_flag( part, "TOW_CABLE" ) ) { + if( vpi_here.has_flag( "TOW_CABLE" ) ) { invalidate_towing( true ); } else { - if( part_flag( p, "POWER_TRANSFER" ) ) { + if( vpi.has_flag( "POWER_TRANSFER" ) ) { remove_remote_part( part ); } - item part_as_item = parts[part].properties_to_item(); - here.add_item_or_charges( pos, part_as_item ); + here.add_item_or_charges( pos, vp_here.properties_to_item() ); remove_part( part, *handler_ptr ); } } @@ -7129,18 +7107,21 @@ int vehicle::damage_direct( map &here, int p, int dmg, const damage_type_id &typ if( ( static_cast( p ) >= parts.size() ) || parts[p].removed ) { return dmg; } + vehicle_part &vp = parts[p]; + const vpart_info &vpi = vp.info(); + const tripoint vppos = global_part_pos3( vp ); // If auto-driving and damage happens, bail out if( is_autodriving ) { stop_autodriving(); } - here.set_memory_seen_cache_dirty( global_part_pos3( p ) ); - if( parts[p].is_broken() ) { + here.set_memory_seen_cache_dirty( vppos ); + if( vp.is_broken() ) { return break_off( here, p, dmg ); } - int tsh = std::min( 20, part_info( p ).durability / 10 ); + int tsh = std::min( 20, vpi.durability / 10 ); if( dmg < tsh && type != damage_pure ) { - if( type == damage_heat && parts[p].is_fuel_store() ) { + if( type == damage_heat && vp.is_fuel_store() ) { explode_fuel( p, type ); } @@ -7148,11 +7129,11 @@ int vehicle::damage_direct( map &here, int p, int dmg, const damage_type_id &typ } if( !type->no_resist ) { - dmg -= std::min( dmg, part_info( p ).damage_reduction.at( type ) ); + dmg -= std::min( dmg, vpi.damage_reduction.at( type ) ); } - int dres = dmg - parts[p].hp(); - if( mod_hp( parts[ p ], -dmg ) ) { - if( is_flyable() && !rotors.empty() && !parts[p].info().has_flag( VPFLAG_SIMPLE_PART ) ) { + int dres = dmg - vp.hp(); + if( mod_hp( vp, -dmg ) ) { + if( is_flyable() && !rotors.empty() && !vpi.has_flag( VPFLAG_SIMPLE_PART ) ) { // If we break a part, we can no longer fly the vehicle. set_flyable( false ); } @@ -7161,12 +7142,12 @@ int vehicle::damage_direct( map &here, int p, int dmg, const damage_type_id &typ pivot_dirty = true; // destroyed parts lose any contained fuels, battery charges or ammo - leak_fuel( parts [ p ] ); + leak_fuel( vp ); - for( const item &e : parts[p].items ) { - here.add_item_or_charges( global_part_pos3( p ), e ); + for( const item &e : vp.items ) { + here.add_item_or_charges( vppos, e ); } - parts[p].items.clear(); + vp.items.clear(); invalidate_mass(); coeff_air_changed = true; @@ -7175,27 +7156,26 @@ int vehicle::damage_direct( map &here, int p, int dmg, const damage_type_id &typ refresh(); } - if( parts[p].is_fuel_store() ) { + if( vp.is_fuel_store() ) { explode_fuel( p, type ); - } else if( parts[ p ].is_broken() && part_flag( p, "UNMOUNT_ON_DAMAGE" ) ) { + } else if( vp.is_broken() && vpi.has_flag( "UNMOUNT_ON_DAMAGE" ) ) { monster *mon = get_monster( p ); if( mon != nullptr && mon->has_effect( effect_harnessed ) ) { mon->remove_effect( effect_harnessed ); } - if( part_flag( p, "TOW_CABLE" ) ) { + if( vpi.has_flag( "TOW_CABLE" ) ) { invalidate_towing( true ); } else { - item part_as_item = parts[p].properties_to_item(); - add_msg_if_player_sees( global_part_pos3( p ), m_bad, _( "The %1$s's %2$s is disconnected!" ), name, - parts[p].name() ); - if( part_flag( p, "POWER_TRANSFER" ) ) { + item part_as_item = vp.properties_to_item(); + add_msg_if_player_sees( vppos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, vp.name() ); + if( vpi.has_flag( "POWER_TRANSFER" ) ) { remove_remote_part( p ); part_as_item.set_damage( 0 ); } else { - part_as_item.set_damage( part_info( p ).base_item.obj().damage_max() - 1 ); + part_as_item.set_damage( vpi.base_item.obj().damage_max() - 1 ); } if( !magic && !part_as_item.has_flag( flag_AUTO_DELETE_CABLE ) ) { - here.add_item_or_charges( global_part_pos3( p ), part_as_item ); + here.add_item_or_charges( vppos, part_as_item ); } if( !g || &get_map() != &here ) { MapgenRemovePartHandler handler( here ); diff --git a/src/vehicle.h b/src/vehicle.h index 3135e50b5605e..a654356779afc 100644 --- a/src/vehicle.h +++ b/src/vehicle.h @@ -1288,10 +1288,6 @@ class vehicle // with the same flag on the X and Y Axis std::vector> find_lines_of_parts( int part, const std::string &flag ) const; - // returns true if given flag is present for given part index - bool part_flag( int p, const std::string &f ) const; - bool part_flag( int p, vpart_bitflags f ) const; - // Translate mount coordinates "p" using current pivot direction and anchor and return tile coordinates point coord_translate( const point &p ) const; diff --git a/src/vehicle_display.cpp b/src/vehicle_display.cpp index 8837768a3f0f1..6e570d3230d27 100644 --- a/src/vehicle_display.cpp +++ b/src/vehicle_display.cpp @@ -149,7 +149,8 @@ int vehicle::print_part_list( const catacurses::window &win, int y1, const int m std::vector pl = this->parts_at_relative( parts[p].mount, true, include_fakes ); int y = y1; for( size_t i = 0; i < pl.size(); i++ ) { - const vehicle_part &vp = parts[ pl [ i ] ]; + const vehicle_part &vp = parts[pl[i]]; + const vpart_info &vpi = vp.info(); if( !vp.is_real_or_active_fake() ) { continue; } @@ -178,7 +179,7 @@ int vehicle::print_part_list( const catacurses::window &win, int y1, const int m } } - if( part_flag( pl[i], "CARGO" ) ) { + if( vpi.has_flag( VPFLAG_CARGO ) ) { //~ used/total volume of a cargo vehicle part partname += string_format( _( " (vol: %s/%s %s)" ), format_volume( stored_volume( pl[i] ) ), @@ -186,13 +187,13 @@ int vehicle::print_part_list( const catacurses::window &win, int y1, const int m volume_units_abbr() ); } - bool armor = part_flag( pl[i], "ARMOR" ); + const bool armor = vpi.has_flag( VPFLAG_ARMOR ); std::string left_sym; std::string right_sym; if( armor ) { left_sym = "("; right_sym = ")"; - } else if( part_info( pl[i] ).location == part_location_structure ) { + } else if( vpi.location == part_location_structure ) { left_sym = "["; right_sym = "]"; } else { diff --git a/src/vehicle_move.cpp b/src/vehicle_move.cpp index c86f3b753d52e..29ef5ecd83382 100644 --- a/src/vehicle_move.cpp +++ b/src/vehicle_move.cpp @@ -859,7 +859,7 @@ veh_collision vehicle::part_collision( int part, const tripoint &p, // Typical rotor tip speed in MPH * 100. int rotor_velocity = 45600; // Non-vehicle collisions can't happen when the vehicle is not moving - int &coll_velocity = ( part_info( part ).rotor_diameter() == 0 ) ? + int &coll_velocity = ( parts[part].info().rotor_diameter() == 0 ) ? ( vert_coll ? vertical_velocity : velocity ) : rotor_velocity; if( !just_detect && coll_velocity == 0 ) { @@ -896,7 +896,7 @@ veh_collision vehicle::part_collision( int part, const tripoint &p, if( armor_part >= 0 ) { ret.part = armor_part; } - const vehicle_part &vp = this->part( ret.part ); + vehicle_part &vp = this->part( ret.part ); const vpart_info &vpi = vp.info(); // Let's calculate type of collision & mass of object we hit float mass2 = 0.0f; @@ -950,11 +950,12 @@ veh_collision vehicle::part_collision( int part, const tripoint &p, // Calculate mass AFTER checking for collision // because it involves iterating over all cargo // Rotors only use rotor mass in calculation. - const float mass = ( part_info( ret.part ).rotor_diameter() > 0 ) ? - to_kilogram( parts[ ret.part ].base.weight() ) : to_kilogram( total_mass() ); + const float mass = vpi.rotor_diameter() > 0 + ? to_kilogram( vp.base.weight() ) + : to_kilogram( total_mass() ); //Calculate damage resulting from d_E - const itype *type = item::find_type( part_info( ret.part ).base_item ); + const itype *type = item::find_type( vpi.base_item ); const auto &mats = type->materials; float mat_total = type->mat_portion_total == 0 ? 1 : type->mat_portion_total; float vpart_dens = 0.0f; @@ -1068,10 +1069,10 @@ veh_collision vehicle::part_collision( int part, const tripoint &p, // No blood from hallucinations if( !critter->is_hallucination() ) { - if( part_flag( ret.part, "SHARP" ) ) { - parts[ret.part].blood += ( 20 + dam ) * 5; + if( vpi.has_flag( "SHARP" ) ) { + vp.blood += 100 + 5 * dam; } else if( dam > rng( 10, 30 ) ) { - parts[ret.part].blood += ( 10 + dam / 2 ) * 5; + vp.blood += 50 + dam / 2 * 5; } check_environmental_effects = true; @@ -1085,12 +1086,12 @@ veh_collision vehicle::part_collision( int part, const tripoint &p, if( ph != nullptr ) { ph->hitall( dam, 40, driver ); } else { - const int armor = part_flag( ret.part, "SHARP" ) ? + const int armor = vpi.has_flag( "SHARP" ) ? critter->get_armor_type( damage_cut, bodypart_id( "torso" ) ) : critter->get_armor_type( damage_bash, bodypart_id( "torso" ) ); dam = std::max( 0, dam - armor ); critter->apply_damage( driver, bodypart_id( "torso" ), dam ); - if( part_flag( ret.part, "SHARP" ) ) { + if( vpi.has_flag( "SHARP" ) ) { critter->add_effect( effect_source( driver ), effect_bleed, 1_minutes * rng( 1, dam ), critter->get_random_body_part_of_type( body_part_type::type::torso ) ); } else if( dam > 18 && rng( 1, 20 ) > 15 ) { @@ -1144,15 +1145,15 @@ veh_collision vehicle::part_collision( int part, const tripoint &p, if( time_stunned > 0_turns ) { //~ 1$s - vehicle name, 2$s - part name, 3$s - NPC or monster add_msg( m_warning, _( "Your %1$s's %2$s rams into %3$s and stuns it!" ), - name, parts[ ret.part ].name(), ret.target_name ); + name, vp.name(), ret.target_name ); } else { //~ 1$s - vehicle name, 2$s - part name, 3$s - NPC or monster add_msg( m_warning, _( "Your %1$s's %2$s rams into %3$s!" ), - name, parts[ ret.part ].name(), ret.target_name ); + name, vp.name(), ret.target_name ); } } - if( part_flag( ret.part, "SHARP" ) ) { + if( vpi.has_flag( "SHARP" ) ) { critter->bleed(); } else { sounds::sound( p, 20, sounds::sound_t::combat, snd, false, "smash_success", "hit_vehicle" ); @@ -1163,11 +1164,11 @@ veh_collision vehicle::part_collision( int part, const tripoint &p, if( !snd.empty() ) { //~ 1$s - vehicle name, 2$s - part name, 3$s - collision object name, 4$s - sound message add_msg( m_warning, _( "Your %1$s's %2$s rams into %3$s with a %4$s" ), - name, parts[ ret.part ].name(), ret.target_name, snd ); + name, vp.name(), ret.target_name, snd ); } else { //~ 1$s - vehicle name, 2$s - part name, 3$s - collision object name add_msg( m_warning, _( "Your %1$s's %2$s rams into %3$s." ), - name, parts[ ret.part ].name(), ret.target_name ); + name, vp.name(), ret.target_name ); } } diff --git a/src/vehicle_use.cpp b/src/vehicle_use.cpp index 0e87e4a1352c4..17411405454c6 100644 --- a/src/vehicle_use.cpp +++ b/src/vehicle_use.cpp @@ -141,7 +141,8 @@ void vehicle::control_doors() if( motorized_idx == -1 ) { continue; } - if( !require_flag.empty() && !part_flag( motorized_idx, require_flag ) ) { + vehicle_part &vp = part( motorized_idx ); + if( !require_flag.empty() && !vp.info().has_flag( require_flag ) ) { continue; } if( new_open || can_close( motorized_idx, get_player_character() ) ) { @@ -157,7 +158,8 @@ void vehicle::control_doors() if( motorized_idx == -1 ) { continue; } - if( !require_flag.empty() && !part_flag( motorized_idx, require_flag ) ) { + vehicle_part &vp = part( motorized_idx ); + if( !require_flag.empty() && !vp.info().has_flag( require_flag ) ) { continue; } lock_or_unlock( motorized_idx, new_lock ); @@ -1298,9 +1300,9 @@ bool vehicle::can_close( int part_index, Character &who ) void vehicle::open_all_at( int p ) { - std::vector parts_here = parts_at_relative( parts[p].mount, true, true ); - for( int &elem : parts_here ) { - if( part_flag( elem, VPFLAG_OPENABLE ) ) { + for( const int elem : parts_at_relative( parts[p].mount, true, true ) ) { + const vehicle_part &vp = parts[elem]; + if( vp.info().has_flag( VPFLAG_OPENABLE ) ) { // Note that this will open multi-square and non-multipart parts in the tile. This // means that adjacent open multi-square openables can still have closed stuff // on same tile after this function returns @@ -1586,7 +1588,11 @@ void vehicle::use_monster_capture( int part, const tripoint &pos ) void vehicle::use_harness( int part, const tripoint &pos ) { - if( parts[part].is_unavailable() || parts[part].removed ) { + const vehicle_part &vp = parts[part]; + const vpart_info &vpi = vp.info(); + + if( vp.is_unavailable() || vp.removed ) { + debugmsg( "use_harness called on invalid part" ); return; } if( !g->is_empty( pos ) ) { @@ -1625,7 +1631,7 @@ void vehicle::use_harness( int part, const tripoint &pos ) } else if( !m.has_flag( MF_PET_MOUNTABLE ) && !m.has_flag( MF_PET_HARNESSABLE ) ) { add_msg( m_info, _( "This creature cannot be harnessed." ) ); return; - } else if( !part_flag( part, Harness_Bodytype ) && !part_flag( part, "HARNESS_any" ) ) { + } else if( !vpi.has_flag( Harness_Bodytype ) && !vpi.has_flag( "HARNESS_any" ) ) { add_msg( m_info, _( "The harness is not adapted for this creature morphology." ) ); return; }