From d861e9a4940d1298e3374aef81b7cc6e6f31fbb3 Mon Sep 17 00:00:00 2001 From: PatrikLundell Date: Mon, 3 Feb 2025 23:18:05 +0100 Subject: [PATCH] vehicle position -> absolute --- src/activity_actor.cpp | 11 +- src/activity_item_handling.cpp | 4 +- src/debug_menu.cpp | 4 +- src/grab.cpp | 25 ++-- src/handle_liquid.cpp | 6 +- src/item_location.cpp | 6 +- src/iuse_actor.cpp | 2 +- src/lightmap.cpp | 4 +- src/map.cpp | 26 ++-- src/map.h | 2 +- src/mapgen.cpp | 17 +-- src/npcmove.cpp | 4 +- src/ranged.cpp | 5 +- src/savegame_json.cpp | 7 +- src/turret.cpp | 18 ++- src/veh_appliance.cpp | 5 +- src/veh_interact.cpp | 2 +- src/veh_shape.cpp | 16 ++- src/veh_utils.cpp | 2 +- src/vehicle.cpp | 233 ++++++++++++++++++------------- src/vehicle.h | 14 +- src/vehicle_move.cpp | 13 +- src/vehicle_use.cpp | 41 ++++-- tests/vehicle_export_test.cpp | 5 +- tests/vehicle_fake_part_test.cpp | 2 +- tests/vehicle_power_test.cpp | 2 +- tests/vehicle_ramp_test.cpp | 4 +- tests/vehicle_test.cpp | 6 +- tests/vehicle_turrets_test.cpp | 2 +- 29 files changed, 288 insertions(+), 200 deletions(-) diff --git a/src/activity_actor.cpp b/src/activity_actor.cpp index d9d0f9879dbb6..f8b00cf58aa15 100644 --- a/src/activity_actor.cpp +++ b/src/activity_actor.cpp @@ -1356,8 +1356,9 @@ bikerack_racking_activity_actor::bikerack_racking_activity_actor( const vehicle const vehicle &racked_vehicle, const std::vector &racks ) : racks( racks ) { - parent_vehicle_pos = parent_vehicle.bub_part_pos( 0 ); - racked_vehicle_pos = racked_vehicle.bub_part_pos( 0 ); + map &here = get_map(); + parent_vehicle_pos = parent_vehicle.bub_part_pos( &here, 0 ); + racked_vehicle_pos = racked_vehicle.bub_part_pos( &here, 0 ); } void bikerack_racking_activity_actor::start( player_activity &act, Character & ) @@ -1582,7 +1583,8 @@ bikerack_unracking_activity_actor::bikerack_unracking_activity_actor( const vehi const std::vector &parts, const std::vector &racks ) : parts( parts ), racks( racks ) { - parent_vehicle_pos = parent_vehicle.bub_part_pos( 0 ); + map &here = get_map(); + parent_vehicle_pos = parent_vehicle.bub_part_pos( &here, 0 ); } void bikerack_unracking_activity_actor::start( player_activity &act, Character & ) @@ -8008,8 +8010,9 @@ bool vehicle_folding_activity_actor::fold_vehicle( Character &p, bool check_only vehicle_folding_activity_actor::vehicle_folding_activity_actor( const vehicle &target ) { + map &here = get_map(); folding_time = target.folding_time(); - target_pos = target.bub_part_pos( 0 ); + target_pos = target.bub_part_pos( &here, 0 ); } void vehicle_folding_activity_actor::start( player_activity &act, Character &p ) diff --git a/src/activity_item_handling.cpp b/src/activity_item_handling.cpp index db13b2c860059..967a5c34d6744 100644 --- a/src/activity_item_handling.cpp +++ b/src/activity_item_handling.cpp @@ -219,14 +219,14 @@ static bool handle_spillable_contents( Character &c, item &it, map &m ) static void put_into_vehicle( Character &c, item_drop_reason reason, const std::list &items, const vpart_reference &vpr ) { + map &here = get_map(); if( items.empty() ) { return; } c.invalidate_weight_carried_cache(); vehicle_part &vp = vpr.part(); vehicle &veh = vpr.vehicle(); - const tripoint_bub_ms where = veh.bub_part_pos( vp ); - map &here = get_map(); + const tripoint_bub_ms where = veh.bub_part_pos( &here, vp ); int items_did_not_fit_count = 0; int into_vehicle_count = 0; const std::string part_name = vp.info().name(); diff --git a/src/debug_menu.cpp b/src/debug_menu.cpp index 8962fc07d9ff4..94e1287d67697 100644 --- a/src/debug_menu.cpp +++ b/src/debug_menu.cpp @@ -3731,6 +3731,8 @@ static void vehicle_battery_charge() static void vehicle_export() { + map &here = get_map(); + if( optional_vpart_position ovp = get_map().veh_at( get_avatar().pos_bub() ) ) { cata_path export_dir{ cata_path::root_path::user, "export_dir" }; assure_dir_exist( export_dir ); @@ -3742,7 +3744,7 @@ static void vehicle_export() try { write_to_file( veh_path, [&]( std::ostream & fout ) { JsonOut jsout( fout ); - ovp->vehicle().refresh(); + ovp->vehicle().refresh( &here ); vehicle_prototype::save_vehicle_as_prototype( ovp->vehicle(), jsout ); } ); } catch( const std::exception &err ) { diff --git a/src/grab.cpp b/src/grab.cpp index 20b6f29820c7b..48fca6c58aa7c 100644 --- a/src/grab.cpp +++ b/src/grab.cpp @@ -19,7 +19,8 @@ bool game::grabbed_veh_move( const tripoint_rel_ms &dp ) { - const optional_vpart_position grabbed_vehicle_vp = m.veh_at( u.pos_bub() + u.grab_point ); + map &here = get_map(); + const optional_vpart_position grabbed_vehicle_vp = m.veh_at( u.pos_bub( &here ) + u.grab_point ); if( !grabbed_vehicle_vp ) { add_msg( m_info, _( "No vehicle at grabbed point." ) ); u.grab( object_type::NONE ); @@ -37,7 +38,7 @@ bool game::grabbed_veh_move( const tripoint_rel_ms &dp ) u.grab( object_type::NONE ); return false; } - const vehicle *veh_under_player = veh_pointer_or_null( m.veh_at( u.pos_bub() ) ); + const vehicle *veh_under_player = veh_pointer_or_null( m.veh_at( u.pos_bub( &here ) ) ); if( grabbed_vehicle == veh_under_player ) { u.grab_point = - dp; return false; @@ -106,7 +107,7 @@ bool game::grabbed_veh_move( const tripoint_rel_ms &dp ) units::angle face_delta = angle_delta( grabbed_vehicle->face.dir(), my_dir.dir() ); tileray my_pos_dir; - tripoint_rel_ms my_angle = u.pos_bub() - grabbed_vehicle->pos_bub(); + tripoint_rel_ms my_angle = u.pos_bub( &here ) - grabbed_vehicle->pos_bub( &here ); my_pos_dir.init( my_angle.xy() ); back_of_vehicle = ( angle_delta( grabbed_vehicle->face.dir(), my_pos_dir.dir() ) > 90_degrees ); invalid_veh_face = ( face_delta > vehicles::steer_increment * 2 - 1_degrees && @@ -120,7 +121,7 @@ bool game::grabbed_veh_move( const tripoint_rel_ms &dp ) } else { str_req = max_str_req / 10; //determine movecost for terrain touching wheels - const tripoint_bub_ms vehpos = grabbed_vehicle->pos_bub(); + const tripoint_bub_ms vehpos = grabbed_vehicle->pos_bub( &here ); for( int p : wheel_indices ) { const tripoint_bub_ms wheel_pos = vehpos + grabbed_vehicle->part( p ).precalc[0]; const int mapcost = m.move_cost( wheel_pos, grabbed_vehicle ); @@ -147,7 +148,7 @@ bool game::grabbed_veh_move( const tripoint_rel_ms &dp ) if( str_req <= str ) { if( str_req == max_str_req ) { //if vehicle has no wheels, make a noise. - sounds::sound( grabbed_vehicle->pos_bub(), str_req * 2, sounds::sound_t::movement, + sounds::sound( grabbed_vehicle->pos_bub( &here ), str_req * 2, sounds::sound_t::movement, _( "a scraping noise." ), true, "misc", "scraping" ); } //calculate exertion factor and movement penalty @@ -220,9 +221,9 @@ bool game::grabbed_veh_move( const tripoint_rel_ms &dp ) // Grabbed part has to stay at distance 1 to the player // and in roughly the same direction. - const tripoint_bub_ms new_part_pos = grabbed_vehicle->pos_bub() + + const tripoint_bub_ms new_part_pos = grabbed_vehicle->pos_bub( &here ) + grabbed_vehicle->part( grabbed_part ).precalc[1]; - const tripoint_bub_ms expected_pos = u.pos_bub() + dp + md_next_grab; + const tripoint_bub_ms expected_pos = u.pos_bub( &here ) + dp + md_next_grab; tripoint_rel_ms actual_dir = tripoint_rel_ms( ( expected_pos - new_part_pos ).xy(), 0 ); bool failed = false; @@ -234,8 +235,8 @@ bool game::grabbed_veh_move( const tripoint_rel_ms &dp ) while( !no_player_collision ) { no_player_collision = true; for( const vpart_reference &vp : grabbed_vehicle->get_all_parts() ) { - if( grabbed_vehicle->pos_bub() + - vp.part().precalc[1] + actual_dir == u.pos_bub() + skip ) { + if( grabbed_vehicle->pos_bub( &here ) + + vp.part().precalc[1] + actual_dir == u.pos_bub( &here ) + skip ) { no_player_collision = false; break; } @@ -253,7 +254,7 @@ bool game::grabbed_veh_move( const tripoint_rel_ms &dp ) } } // Set player location to illegal value so it can't collide with vehicle. - const tripoint_bub_ms player_prev = u.pos_bub(); + const tripoint_bub_ms player_prev = u.pos_bub( &here ); u.setpos( tripoint_bub_ms::zero, false ); std::vector colls; failed = grabbed_vehicle->collision( colls, actual_dir, true ); @@ -296,7 +297,7 @@ bool game::grabbed_veh_move( const tripoint_rel_ms &dp ) add_msg( _( "You let go of the %1$s as it starts to fall." ), grabbed_vehicle->disp_name() ); u.grab( object_type::NONE ); u.grab_point = tripoint_rel_ms::zero; - m.set_seen_cache_dirty( grabbed_vehicle->pos_bub() ); + m.set_seen_cache_dirty( grabbed_vehicle->pos_bub( &here ) ); return true; } } else { @@ -307,7 +308,7 @@ bool game::grabbed_veh_move( const tripoint_rel_ms &dp ) for( int p : wheel_indices ) { if( one_in( 2 ) ) { vehicle_part &vp_wheel = grabbed_vehicle->part( p ); - tripoint_bub_ms wheel_p = grabbed_vehicle->bub_part_pos( vp_wheel ); + tripoint_bub_ms wheel_p = grabbed_vehicle->bub_part_pos( &here, vp_wheel ); grabbed_vehicle->handle_trap( wheel_p, vp_wheel ); } } diff --git a/src/handle_liquid.cpp b/src/handle_liquid.cpp index f26ac49081ed3..062c3ccb9241b 100644 --- a/src/handle_liquid.cpp +++ b/src/handle_liquid.cpp @@ -52,10 +52,11 @@ static const flag_id json_flag_FROM_FROZEN_LIQUID( "FROM_FROZEN_LIQUID" ); static void serialize_liquid_source( player_activity &act, const vehicle &veh, const int part_num, const item &liquid ) { + map &here = get_map(); act.values.push_back( static_cast( liquid_source_type::VEHICLE ) ); act.values.push_back( part_num ); if( part_num != -1 ) { - act.coords.push_back( get_map().get_abs( veh.bub_part_pos( part_num ) ) ); + act.coords.push_back( here.get_abs( veh.bub_part_pos( &here, part_num ) ) ); } else { act.coords.push_back( veh.pos_abs() ); } @@ -84,9 +85,10 @@ static void serialize_liquid_source( player_activity &act, const tripoint_bub_ms static void serialize_liquid_target( player_activity &act, const vpart_reference &vp ) { + map &here = get_map(); act.values.push_back( static_cast( liquid_target_type::VEHICLE ) ); act.values.push_back( 0 ); // dummy - act.coords.push_back( get_map().get_abs( vp.vehicle().bub_part_pos( 0 ) ) ); + act.coords.push_back( here.get_abs( vp.vehicle().bub_part_pos( &here, 0 ) ) ); act.values.push_back( vp.part_index() ); // tank part index } diff --git a/src/item_location.cpp b/src/item_location.cpp index 09f2d209a550b..bb1120831b6ee 100644 --- a/src/item_location.cpp +++ b/src/item_location.cpp @@ -485,7 +485,8 @@ class item_location::impl::item_on_vehicle : public item_location::impl } tripoint_bub_ms pos_bub() const override { - return cur.veh.bub_part_pos( cur.part ); + map &here = get_map(); + return cur.veh.bub_part_pos( &here, cur.part ); } Character *carrier() const override { @@ -532,9 +533,10 @@ class item_location::impl::item_on_vehicle : public item_location::impl return 0; } + map &here = get_map(); item *obj = target(); int mv = ch.item_handling_cost( *obj, true, VEHICLE_HANDLING_PENALTY, qty ); - mv += 100 * rl_dist( ch.pos_bub(), cur.veh.bub_part_pos( cur.part ) ); + mv += 100 * rl_dist( ch.pos_bub( &here ), cur.veh.bub_part_pos( &here, cur.part ) ); // TODO: handle unpacking costs diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 22253bccacd3b..c030ba57786b2 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -5056,7 +5056,7 @@ std::optional link_up_actor::link_tow_cable( Character *p, item &it, const auto can_link = [&here]( const tripoint_bub_ms & point ) { const optional_vpart_position ovp = here.veh_at( point ); - return ovp && ovp->vehicle().is_external_part(&here, point ); + return ovp && ovp->vehicle().is_external_part( &here, point ); }; const std::optional pnt_ = choose_adjacent_highlight( diff --git a/src/lightmap.cpp b/src/lightmap.cpp index d6df725690b2c..7ae38b722bdc3 100644 --- a/src/lightmap.cpp +++ b/src/lightmap.cpp @@ -589,7 +589,7 @@ void map::generate_lightmap( const int zlev ) for( const vehicle_part *pt : lights ) { const vpart_info &vp = pt->info(); - tripoint_bub_ms src = v->bub_part_pos( *pt ); + tripoint_bub_ms src = v->bub_part_pos( this, *pt ); if( !inbounds( src ) ) { continue; @@ -1123,7 +1123,7 @@ void map::build_seen_cache( const tripoint_bub_ms &origin, const int target_z, i continue; // Player not at camera control, so cameras don't work } - const tripoint_bub_ms mirror_pos = veh->bub_part_pos( vp_mirror ); + const tripoint_bub_ms mirror_pos = veh->bub_part_pos( this, vp_mirror ); // Determine how far the light has already traveled so mirrors // don't cheat the light distance falloff. diff --git a/src/map.cpp b/src/map.cpp index 433505a924dd8..14a26eaa06028 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -470,7 +470,7 @@ void map::add_vehicle_to_cache( vehicle *veh ) if( vpr.part().removed ) { continue; } - const tripoint_bub_ms p = veh->bub_part_pos( vpr.part() ); + const tripoint_bub_ms p = veh->bub_part_pos( this, vpr.part() ); level_cache &ch = get_cache( p.z() ); ch.set_veh_cached_parts( p, *veh, static_cast( vpr.part_index() ) ); if( inbounds( p ) ) { @@ -957,7 +957,7 @@ vehicle *map::move_vehicle( vehicle &veh, const tripoint_rel_ms &dp, const tiler for( const int vp_wheel_idx : wheel_indices ) { vehicle_part &vp_wheel = veh.part( vp_wheel_idx ); const vpart_info &vpi_wheel = vp_wheel.info(); - const tripoint_bub_ms wheel_p = veh.bub_part_pos( vp_wheel ); + const tripoint_bub_ms wheel_p = veh.bub_part_pos( this, vp_wheel ); if( one_in( 2 ) && displace_water( wheel_p ) ) { sounds::sound( wheel_p, 4, sounds::sound_t::movement, _( "splash!" ), false, "environment", "splash" ); @@ -1026,8 +1026,8 @@ float map::vehicle_vehicle_collision( vehicle &veh, vehicle &veh2, // Check whether avatar sees the collision, and log a message if so const avatar &you = get_avatar(); - const tripoint_bub_ms part1_pos = veh.bub_part_pos( vp1 ); - const tripoint_bub_ms part2_pos = veh2.bub_part_pos( vp2 ); + const tripoint_bub_ms part1_pos = veh.bub_part_pos( this, vp1 ); + const tripoint_bub_ms part2_pos = veh2.bub_part_pos( this, vp2 ); if( you.sees( part1_pos ) || you.sees( part2_pos ) ) { //~ %1$s: first vehicle name (without "the") //~ %2$s: first part name @@ -1304,7 +1304,7 @@ VehicleList map::get_vehicles( const tripoint_bub_ms &start, const tripoint_bub_ elem->sm_pos.z() = cz; wrapped_vehicle w; w.v = elem.get(); - w.pos = w.v->pos_bub(); + w.pos = w.v->pos_bub( this ); vehs.push_back( w ); } } @@ -1529,7 +1529,7 @@ bool map::displace_vehicle( vehicle &veh, const tripoint_rel_ms &dp, const bool continue; } Creature *psg = r.psg; - const tripoint_bub_ms part_pos = veh.bub_part_pos( prt ); + const tripoint_bub_ms part_pos = veh.bub_part_pos( this, prt ); if( psg == nullptr ) { debugmsg( "Empty passenger for part #%d at %d,%d,%d player at %d,%d,%d?", prt, part_pos.x(), part_pos.y(), part_pos.z(), @@ -8171,7 +8171,7 @@ void map::loadn( const point_bub_sm &grid, bool update_vehicles ) vehicle *veh = iter->get(); if( veh->part_count() > 0 ) { // Always fix submap coordinates for easier Z-level-related operations - veh->sm_pos = abs_sub.xy() + tripoint_rel_sm{ rebase_rel(grid), z}; + veh->sm_pos = abs_sub.xy() + tripoint_rel_sm{ rebase_rel( grid ), z}; iter++; if( main_inbounds ) { _main_requires_cleanup = true; @@ -8593,7 +8593,7 @@ void map::actualize( const tripoint_rel_sm &grid ) const item &base_const = vp.part().get_base(); const_cast( base_const ).overflow( vp.pos_bub() ); } - veh->refresh(); + veh->refresh( this ); } const time_duration time_since_last_actualize = calendar::turn - tmpsub->last_touched; @@ -9428,12 +9428,14 @@ void map::build_floor_caches() static void vehicle_caching_internal( level_cache &zch, const vpart_reference &vp, vehicle *v ) { + map &here = + get_map(); // TODO: Check is this is actually reasonable. Probably need to feed the map in. auto &outside_cache = zch.outside_cache; auto &transparency_cache = zch.transparency_cache; auto &floor_cache = zch.floor_cache; const size_t part = vp.part_index(); - const tripoint_bub_ms part_pos = v->bub_part_pos( vp.part() ); + const tripoint_bub_ms part_pos = v->bub_part_pos( &here, vp.part() ); bool vehicle_is_opaque = vp.has_feature( VPFLAG_OPAQUE ) && !vp.part().is_broken(); @@ -9458,8 +9460,10 @@ static void vehicle_caching_internal( level_cache &zch, const vpart_reference &v static void vehicle_caching_internal_above( level_cache &zch_above, const vpart_reference &vp, vehicle *v ) { + map &here = + get_map(); // TODO: Check is this is actually reasonable. Probably need to feed the map in. if( vp.has_feature( VPFLAG_ROOF ) || vp.has_feature( VPFLAG_OPAQUE ) ) { - const tripoint_bub_ms part_pos = v->bub_part_pos( vp.part() ); + const tripoint_bub_ms part_pos = v->bub_part_pos( &here, vp.part() ); zch_above.floor_cache[part_pos.x()][part_pos.y()] = true; } } @@ -9472,7 +9476,7 @@ void map::do_vehicle_caching( int z ) } for( vehicle *v : ch->vehicle_list ) { for( const vpart_reference &vp : v->get_all_parts_with_fakes() ) { - const tripoint_bub_ms part_pos = v->bub_part_pos( vp.part() ); + const tripoint_bub_ms part_pos = v->bub_part_pos( this, vp.part() ); if( !inbounds( part_pos.xy() ) ) { continue; } diff --git a/src/map.h b/src/map.h index dd7dc69defe58..6dbe8d5801461 100644 --- a/src/map.h +++ b/src/map.h @@ -803,7 +803,7 @@ class map // Returns the wheel area of the vehicle multiplied by traction of the surface // When ignore_movement_modifiers is set to true, it returns the area of the wheels touching the ground // TODO: Remove the ugly sinking vehicle hack - float vehicle_wheel_traction( const vehicle &veh, bool ignore_movement_modifiers = false ) const; + float vehicle_wheel_traction( const vehicle &veh, bool ignore_movement_modifiers = false ); // Executes vehicle-vehicle collision based on vehicle::collision results // Returns impulse of the executed collision diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 9a5ee0ad0f0b9..75900ee6b039a 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -6914,7 +6914,7 @@ vehicle *map::add_vehicle( const vproto_id &type, const tripoint_bub_ms &p, cons tripoint_bub_sm quotient; point_sm_ms remainder; std::tie( quotient, remainder ) = coords::project_remain( p_ms ); - veh->sm_pos = abs_sub.xy() + rebase_rel(quotient); + veh->sm_pos = abs_sub.xy() + rebase_rel( quotient ); veh->pos = remainder; veh->init_state( *this, veh_fuel, veh_status, force_status ); veh->place_spawn_items(); @@ -6929,7 +6929,7 @@ vehicle *map::add_vehicle( const vproto_id &type, const tripoint_bub_ms &p, cons vehicle *placed_vehicle = placed_vehicle_up.get(); if( placed_vehicle != nullptr ) { - submap *place_on_submap = get_submap_at_grid( placed_vehicle->sm_pos -abs_sub.xy() ); + submap *place_on_submap = get_submap_at_grid( placed_vehicle->sm_pos - abs_sub.xy() ); if( place_on_submap == nullptr ) { debugmsg( "Tried to add vehicle at %s but the submap is not loaded", placed_vehicle->sm_pos.to_string() ); @@ -6973,7 +6973,7 @@ std::unique_ptr map::add_vehicle_to_map( for( std::vector::const_iterator part = frame_indices.begin(); part != frame_indices.end(); part++ ) { - const tripoint_bub_ms p = veh_to_add->bub_part_pos( *part ); + const tripoint_bub_ms p = veh_to_add->bub_part_pos( this, *part ); if( veh_to_add->part( *part ).is_fake ) { continue; @@ -7016,13 +7016,13 @@ std::unique_ptr map::add_vehicle_to_map( std::unique_ptr handler_ptr; bool did_merge = false; for( const tripoint_abs_ms &map_pos : first_veh->get_points( true ) ) { - const tripoint_bub_ms map_bub_pos = get_bub( map_pos ); // TODO: Make usages use this map. - std::vector parts_to_move = veh_to_add->get_parts_at( map_bub_pos, "", + const tripoint_bub_ms map_bub_pos = get_bub( map_pos ); + std::vector parts_to_move = veh_to_add->get_parts_at( this, map_bub_pos, "", part_status_flag::any ); if( !parts_to_move.empty() ) { // Store target_point by value because first_veh->parts may reallocate // to a different address after install_part() - std::vector first_veh_parts = first_veh->get_parts_at( map_bub_pos, "", + std::vector first_veh_parts = first_veh->get_parts_at( this, map_bub_pos, "", part_status_flag:: any ); // This happens if this location is occupied by a fake part. if( first_veh_parts.empty() || first_veh_parts.front()->is_fake ) { @@ -7058,6 +7058,7 @@ std::unique_ptr map::add_vehicle_to_map( // This is a heuristic: we just assume the default handler is good enough when called // on the main game map. And assume that we run from some mapgen code if called on // another instance. + // TODO: Update logic to be able to work outside of mapgen and in the reality bubble. if( !g || &get_map() != this ) { handler_ptr = std::make_unique( *this ); } @@ -7111,7 +7112,7 @@ std::unique_ptr map::add_vehicle_to_map( veh_to_add->smash( *this ); } - veh_to_add->refresh(); + veh_to_add->refresh( this ); return veh_to_add; } @@ -7227,7 +7228,7 @@ void map::rotate( int turns ) sm->rotate( turns ); for( auto &veh : sm->vehicles ) { - veh->sm_pos = { abs_sub.xy()+ p, z_level }; + veh->sm_pos = { abs_sub.xy() + p, z_level }; } update_vehicle_list( sm, z_level ); diff --git a/src/npcmove.cpp b/src/npcmove.cpp index e7a600f88c127..e6b06fa49ea92 100644 --- a/src/npcmove.cpp +++ b/src/npcmove.cpp @@ -1810,7 +1810,7 @@ void npc::execute_action( npc_action action ) } // A seat is available if we can move there and it's either unassigned or assigned to us auto available_seat = [&]( const vehicle_part & pt ) { - tripoint_bub_ms target = veh->bub_part_pos( pt ); + tripoint_bub_ms target = veh->bub_part_pos( &here, pt ); if( !pt.is_seat() ) { return false; } @@ -1875,7 +1875,7 @@ void npc::execute_action( npc_action action ) const int cur_part = seats[i].second; - tripoint_bub_ms pp = veh->bub_part_pos( cur_part ); + tripoint_bub_ms pp = veh->bub_part_pos( &here, cur_part ); update_path( pp, true ); if( !path.empty() ) { // All is fine diff --git a/src/ranged.cpp b/src/ranged.cpp index b7cc8c4ec36c9..aad3e790bdd99 100644 --- a/src/ranged.cpp +++ b/src/ranged.cpp @@ -514,13 +514,14 @@ target_handler::trajectory target_handler::mode_turret_manual( avatar &you, turr target_handler::trajectory target_handler::mode_turrets( avatar &you, vehicle &veh, const std::vector &turrets ) { + map &here = get_map(); // Find radius of a circle centered at u encompassing all points turrets can aim at // FIXME: this calculation is fine for square distances, but results in an underestimation // when used with real circles int range_total = 0; for( vehicle_part *t : turrets ) { int range = veh.turret_query( *t ).range(); - tripoint_bub_ms pos = veh.bub_part_pos( *t ); + tripoint_bub_ms pos = veh.bub_part_pos( &here, *t ); int res = 0; res = std::max( res, rl_dist( you.pos_bub(), pos + point( range, 0 ) ) ); @@ -3387,7 +3388,7 @@ void target_ui::update_turrets_in_range() for( vehicle_part *t : *vturrets ) { turret_data td = veh->turret_query( *t ); if( td.in_range( here.get_abs( dst ) ) ) { - tripoint_bub_ms src = veh->bub_part_pos( *t ); + tripoint_bub_ms src = veh->bub_part_pos( &here, *t ); turrets_in_range.push_back( {t, line_to( src, dst )} ); } } diff --git a/src/savegame_json.cpp b/src/savegame_json.cpp index bc19b8cc8fc54..52285cc556dea 100644 --- a/src/savegame_json.cpp +++ b/src/savegame_json.cpp @@ -3418,6 +3418,8 @@ void smart_controller_config::serialize( JsonOut &json ) const void vehicle::deserialize( const JsonObject &data ) { + map &here = get_map(); + data.allow_omitted_members(); int fdir = 0; @@ -3496,7 +3498,7 @@ void vehicle::deserialize( const JsonObject &data ) data.read( "fuel_remainder", fuel_remainder ); data.read( "fuel_used_last_turn", fuel_used_last_turn ); - refresh(); + refresh( &here ); point p; zone_data zd; @@ -3540,6 +3542,7 @@ void vehicle::deserialize_parts( const JsonArray &data ) void vehicle::serialize( JsonOut &json ) const { + map &here = get_map(); json.start_object(); json.member( "type", type ); json.member( "posx", pos.x() ); @@ -3583,7 +3586,7 @@ void vehicle::serialize( JsonOut &json ) const if( is_towed() ) { vehicle *tower = tow_data.get_towed_by(); if( tower ) { - other_tow_temp_point = tower->bub_part_pos( tower->get_tow_part() ); + other_tow_temp_point = tower->bub_part_pos( &here, tower->get_tow_part() ); } } json.member( "other_tow_point", other_tow_temp_point ); diff --git a/src/turret.cpp b/src/turret.cpp index 64f3f202b77b9..cd63bf7479e55 100644 --- a/src/turret.cpp +++ b/src/turret.cpp @@ -50,11 +50,12 @@ std::vector vehicle::turrets() std::vector vehicle::turrets( const tripoint_bub_ms &target ) { + map &here = get_map(); std::vector res = turrets(); // exclude turrets not ready to fire or where target is out of range res.erase( std::remove_if( res.begin(), res.end(), [&]( vehicle_part * e ) { return turret_query( *e ).query() != turret_data::status::ready || - rl_dist( bub_part_pos( *e ), target ) > e->base.gun_range(); + rl_dist( bub_part_pos( &here, *e ), target ) > e->base.gun_range(); } ), res.end() ); return res; } @@ -473,7 +474,7 @@ void vehicle::turrets_set_targeting() for( vehicle_part &p : parts ) { if( p.is_turret() ) { turrets.push_back( &p ); - locations.push_back( bub_part_pos( p ) ); + locations.push_back( bub_part_pos( &here, p ) ); } } @@ -488,9 +489,9 @@ void vehicle::turrets_set_targeting() menu.fselected = sel; for( vehicle_part *&p : turrets ) { - menu.addentry( -1, has_part( bub_part_pos( *p ), "TURRET_CONTROLS" ), MENU_AUTOASSIGN, + menu.addentry( -1, has_part( bub_part_pos( &here, *p ), "TURRET_CONTROLS" ), MENU_AUTOASSIGN, "%s [%s]", p->name(), p->enabled ? - _( "auto -> manual" ) : has_part( bub_part_pos( *p ), "TURRET_CONTROLS" ) ? + _( "auto -> manual" ) : has_part( bub_part_pos( &here, *p ), "TURRET_CONTROLS" ) ? _( "manual -> auto" ) : _( "manual (turret control unit required for auto mode)" ) ); } @@ -522,13 +523,14 @@ void vehicle::turrets_set_targeting() void vehicle::turrets_set_mode() { + map &here = get_map(); std::vector turrets; std::vector locations; for( vehicle_part &p : parts ) { if( p.base.is_gun() ) { turrets.push_back( &p ); - locations.push_back( bub_part_pos( p ) ); + locations.push_back( bub_part_pos( &here, p ) ); } } @@ -559,6 +561,8 @@ void vehicle::turrets_set_mode() npc &vehicle_part::get_targeting_npc( vehicle &veh ) { + map &here = get_map(); + // Make a fake NPC to represent the targeting system if( !cpu.brain ) { cpu.brain = std::make_unique(); @@ -578,7 +582,7 @@ npc &vehicle_part::get_targeting_npc( vehicle &veh ) brain.name = string_format( _( "The %s turret" ), get_base().tname( 1 ) ); brain.set_skill_level( get_base().gun_skill(), 8 ); } - cpu.brain->setpos( veh.bub_part_pos( *this ) ); + cpu.brain->setpos( veh.bub_part_pos( &here, *this ) ); cpu.brain->recalc_sight_limits(); return *cpu.brain; } @@ -612,7 +616,7 @@ int vehicle::automatic_fire_turret( vehicle_part &pt ) } // The position of the vehicle part. - tripoint_bub_ms pos = bub_part_pos( pt ); + tripoint_bub_ms pos = bub_part_pos( &here, pt ); // Create the targeting computer's npc npc &cpu = pt.get_targeting_npc( *this ); diff --git a/src/veh_appliance.cpp b/src/veh_appliance.cpp index 8b7958af21518..819e7bfb1dd09 100644 --- a/src/veh_appliance.cpp +++ b/src/veh_appliance.cpp @@ -114,7 +114,7 @@ bool place_appliance( const tripoint_bub_ms &p, const vpart_id &vpart, continue; } if( connected_vehicles.find( &veh_target ) == connected_vehicles.end() ) { - veh->connect(&here, p, trip ); + veh->connect( &here, p, trip ); connected_vehicles.insert( &veh_target ); } } @@ -528,8 +528,9 @@ void veh_app_interact::disconnect() void veh_app_interact::plug() { + map &here = get_map(); const int part = veh->part_at( veh->coord_translate( a_point ) ); - const tripoint_bub_ms pos = veh->bub_part_pos( part ); + const tripoint_bub_ms pos = veh->bub_part_pos( &here, part ); item cord( itype_power_cord ); cord.link_to( *veh, a_point, link_state::automatic ); if( cord.get_use( "link_up" ) ) { diff --git a/src/veh_interact.cpp b/src/veh_interact.cpp index 949c94e9c2f44..ed73215c613d4 100644 --- a/src/veh_interact.cpp +++ b/src/veh_interact.cpp @@ -3334,7 +3334,7 @@ void veh_interact::complete_vehicle( Character &you ) // Save these values now so they aren't lost when parts or vehicles are destroyed. const point_rel_ms part_mount = vp->mount; - const tripoint_bub_ms part_pos = veh.bub_part_pos( *vp ); + const tripoint_bub_ms part_pos = veh.bub_part_pos( &here, *vp ); veh.unlink_cables( part_mount, you, false, /* unneeded as items will be unlinked if the connected part is removed */ diff --git a/src/veh_shape.cpp b/src/veh_shape.cpp index c4335fddeec2a..5db9e88dfbdc4 100644 --- a/src/veh_shape.cpp +++ b/src/veh_shape.cpp @@ -15,9 +15,10 @@ veh_shape::veh_shape( vehicle &vehicle ): veh( vehicle ) { } player_activity veh_shape::start( const tripoint_bub_ms &pos ) { + map &here = get_map(); avatar &you = get_avatar(); - on_out_of_scope cleanup( []() { - get_map().invalidate_map_cache( get_avatar().view_offset.z() ); + on_out_of_scope cleanup( [&here]() { + here.invalidate_map_cache( get_avatar().view_offset.z() ); } ); restore_on_out_of_scope view_offset_prev( you.view_offset ); @@ -28,13 +29,13 @@ player_activity veh_shape::start( const tripoint_bub_ms &pos ) if( !set_cursor_pos( pos ) ) { debugmsg( "failed to set cursor at given part" ); - set_cursor_pos( veh.bub_part_pos( 0 ) ); + set_cursor_pos( veh.bub_part_pos( &here, 0 ) ); } const auto target_ui_cb = make_shared_fast( [&]() { const avatar &you = get_avatar(); - g->draw_cursor_unobscuring( you.pos_bub() + you.view_offset ); + g->draw_cursor_unobscuring( you.pos_bub( &here ) + you.view_offset ); } ); g->add_draw_callback( target_ui_cb ); ui_adaptor ui; @@ -83,11 +84,13 @@ player_activity veh_shape::start( const tripoint_bub_ms &pos ) std::vector veh_shape::parts_under_cursor() const { + map &here = get_map(); + std::vector res; // TODO: tons of methods getting parts from vehicle but all of them seem inadequate? for( int part_idx = 0; part_idx < veh.part_count_real(); part_idx++ ) { const vehicle_part &p = veh.part( part_idx ); - if( veh.bub_part_pos( p ) == get_cursor_pos() && !p.is_fake ) { + if( veh.bub_part_pos( &here, p ) == get_cursor_pos() && !p.is_fake ) { res.emplace_back( veh, part_idx ); } } @@ -127,6 +130,7 @@ std::optional veh_shape::select_part_at_cursor( void veh_shape::change_part_shape( vpart_reference vpr ) const { + map &here = get_map(); vehicle_part &part = vpr.part(); const vpart_info &vpi = part.info(); veh_menu menu( this->veh, _( "Choose cosmetic variant:" ) ); @@ -141,7 +145,7 @@ void veh_shape::change_part_shape( vpart_reference vpr ) const .keep_menu_open() .skip_locked_check() .skip_theft_check() - .location( veh.bub_part_pos( part ).raw() ) + .location( veh.bub_part_pos( &here, part ).raw() ) .select( part.variant == vvid ) .desc( _( "Confirm to save or exit to revert" ) ) .symbol( vv.get_symbol_curses( 0_degrees, false ) ) diff --git a/src/veh_utils.cpp b/src/veh_utils.cpp index 349bb013940df..fb41434490f34 100644 --- a/src/veh_utils.cpp +++ b/src/veh_utils.cpp @@ -483,8 +483,8 @@ bool veh_menu::query() chosen._on_submit(); - veh.refresh(); map &m = get_map(); + veh.refresh( &m ); m.invalidate_visibility_cache(); m.invalidate_map_cache( m.get_abs_sub().z() ); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 394b79e069899..7952fba46e987 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -150,13 +150,13 @@ static const int MAX_WIRE_VEHICLE_SIZE = 24; void DefaultRemovePartHandler::removed( vehicle &veh, const int part ) { + map &here = get_map(); avatar &player_character = get_avatar(); const vehicle_part &vp = veh.part( part ); - const tripoint_bub_ms part_pos = veh.bub_part_pos( vp ); + const tripoint_bub_ms part_pos = veh.bub_part_pos( &here, vp ); // If the player is currently working on the removed part, stop them as it's futile now. const player_activity &act = player_character.activity; - map &here = get_map(); if( act.id() == ACT_VEHICLE && act.moves_left > 0 && act.values.size() > 6 ) { if( veh_pointer_or_null( here.veh_at( tripoint_bub_ms( act.values[0], act.values[1], player_character.posz() ) ) ) == &veh ) { @@ -216,11 +216,12 @@ units::volume vehicle_stack::max_volume() const vehicle::vehicle( const vproto_id &proto_id ) { + map &here = get_map(); face.init( 0_degrees ); move.init( 0_degrees ); if( proto_id.is_empty() ) { - refresh(); // we're not using any blueprint, just return an empty initialized vehicle + refresh( &here ); // we're not using any blueprint, just return an empty initialized vehicle } else if( !proto_id.is_valid() ) { debugmsg( "trying to construct vehicle from invalid prototype '%s'", proto_id.str() ); } else { @@ -232,7 +233,7 @@ vehicle::vehicle( const vproto_id &proto_id ) // The game language may have changed after the blueprint was created, // so translated the prototype name again. name = proto.name.translated(); - refresh(); + refresh( &here ); } } @@ -596,11 +597,13 @@ void vehicle::init_state( map &placed_on, int init_veh_fuel, int init_veh_status auto_select_fuel( parts[p] ); } - refresh(); + refresh( &placed_on ); } void vehicle::activate_magical_follow() { + map &here = get_map(); + for( vehicle_part &vp : parts ) { if( vp.info().fuel_type == fuel_type_mana ) { vp.enabled = true; @@ -610,11 +613,13 @@ void vehicle::activate_magical_follow() vp.enabled = true; } } - refresh(); + refresh( &here ); } void vehicle::activate_animal_follow() { + map &here = get_map(); + for( size_t e = 0; e < parts.size(); e++ ) { vehicle_part &vp = parts[ e ]; if( vp.info().fuel_type == fuel_type_animal ) { @@ -628,7 +633,7 @@ void vehicle::activate_animal_follow() vp.enabled = true; } } - refresh(); + refresh( &here ); } void vehicle::autopilot_patrol() @@ -748,16 +753,16 @@ static int get_turn_from_angle( const units::angle &angle, const tripoint_abs_ms void vehicle::drive_to_local_target( const tripoint_abs_ms &target, bool follow_protocol ) { + map &here = get_map(); Character &player_character = get_player_character(); if( follow_protocol && player_character.in_vehicle ) { - sounds::sound( pos_bub(), 30, sounds::sound_t::alert, + sounds::sound( pos_bub( &here ), 30, sounds::sound_t::alert, string_format( _( "the %s emitting a beep and saying \"Autonomous driving protocols suspended!\"" ), name ) ); stop_autodriving(); return; } - refresh(); - map &here = get_map(); + refresh( &here ); tripoint_abs_ms vehpos = pos_abs(); units::angle angle = get_angle_from_targ( target ); @@ -1084,10 +1089,11 @@ void vehicle::unlock() void vehicle::backfire( const vehicle_part &vp ) const { + map &here = get_map(); // single space after the exclamation mark because it does not end the sentence //~ backfire sound const std::string text = _( "a loud BANG! from the %s" ); // NOLINT(cata-text-style); - const tripoint_bub_ms pos = bub_part_pos( vp ); + const tripoint_bub_ms pos = bub_part_pos( &here, vp ); const int volume = 40 + units::to_watt( part_vpower_w( vp, true ) ) / 10000; sounds::sound( pos, volume, sounds::sound_t::movement, string_format( text, vp.name() ), true, "vehicle", "engine_backfire" ); @@ -1486,6 +1492,7 @@ int vehicle::install_part( const point_rel_ms &dp, const vpart_id &type, item && int vehicle::install_part( const point_rel_ms &dp, vehicle_part &&vp ) { + map &here = get_map(); const vpart_info &vpi = vp.info(); const ret_val valid_mount = can_mount( dp, vpi ); if( !valid_mount.success() ) { @@ -1541,13 +1548,14 @@ int vehicle::install_part( const point_rel_ms &dp, vehicle_part &&vp ) vp_installed.enabled = enable; vp_installed.mount = dp; const int vp_installed_index = parts.size() - 1; - refresh(); + refresh( &here ); coeff_air_changed = true; return vp_installed_index; } std::vector vehicle::find_vehicles_to_rack( int rack ) const { + map &here = get_map(); std::vector rackables; for( const std::vector &maybe_rack : find_lines_of_parts( rack, "BIKE_RACK_VEH" ) ) { std::vector filtered_rack; // only empty racks @@ -1560,8 +1568,8 @@ std::vector vehicle::find_vehicles_to_rack( int rack vehicle *veh_matched = nullptr; std::set parts_matched; for( const int &rack_part : filtered_rack ) { - const tripoint_bub_ms search_pos = bub_part_pos( rack_part ) + offset; - const optional_vpart_position ovp = get_map().veh_at( search_pos ); + const tripoint_bub_ms search_pos = bub_part_pos( &here, rack_part ) + offset; + const optional_vpart_position ovp = here.veh_at( search_pos ); if( !ovp || &ovp->vehicle() == this || ovp->vehicle().is_appliance() ) { continue; } @@ -1680,6 +1688,7 @@ std::vector vehicle::find_vehicles_to_unrack( int r bool vehicle::merge_rackable_vehicle( vehicle *carry_veh, const std::vector &rack_parts ) { + map &here = get_map(); for( const vpart_reference &vpr : this->get_any_parts( "BIKE_RACK_VEH" ) ) { const auto unrackables = find_vehicles_to_unrack( vpr.part_index() ); for( const unrackable_vehicle &unrackable : unrackables ) { @@ -1735,7 +1744,7 @@ bool vehicle::merge_rackable_vehicle( vehicle *carry_veh, const std::vector for( const int &carry_part : carry_veh_structs ) { // The current position on the original vehicle for this part - tripoint_bub_ms carry_pos = carry_veh->bub_part_pos( carry_part ); + tripoint_bub_ms carry_pos = carry_veh->bub_part_pos( &here, carry_part ); bool merged_part = false; for( int rack_part : rack_parts ) { @@ -1822,9 +1831,8 @@ bool vehicle::merge_rackable_vehicle( vehicle *carry_veh, const std::vector // update when we next interact with them zones_dirty = true; remove_fake_parts( /* cleanup = */ true ); - refresh(); + refresh( &here ); - map &here = get_map(); //~ %1$s is the vehicle being loaded onto the bicycle rack add_msg( _( "You load the %1$s on the rack." ), carry_veh->name ); here.destroy_vehicle( carry_veh ); @@ -1853,7 +1861,7 @@ bool vehicle::merge_vehicle_parts( vehicle *veh ) item drop = veh->part_to_item( part ); if( drop.link().t_veh.get() == this ) { if( !veh->magic && part.info().id != vpart_power_cord ) { - const tripoint_bub_ms drop_pos = veh->bub_part_pos( part ); + const tripoint_bub_ms drop_pos = veh->bub_part_pos( &here, part ); drop.reset_link( false, nullptr, -1, true, drop_pos ); here.add_item_or_charges( drop_pos, drop ); } @@ -1868,7 +1876,7 @@ bool vehicle::merge_vehicle_parts( vehicle *veh ) vehicle_part &copied_part = parts.back(); copied_part.mount = part_loc - pos_bub().xy(); - refresh(); + refresh( &here ); } here.destroy_vehicle( veh ); @@ -2014,7 +2022,7 @@ bool vehicle::remove_part( vehicle_part &vp, RemovePartHandler &handler ) return false; } - const tripoint_bub_ms part_loc = bub_part_pos( vp ); + const tripoint_bub_ms part_loc = bub_part_pos( &handler.get_map_ref(), vp ); if( !handler.get_map_ref().inbounds( part_loc ) ) { debugmsg( "vehicle::remove_part part '%s' at mount %s bub pos %s is out of map " @@ -2126,7 +2134,7 @@ bool vehicle::remove_part( vehicle_part &vp, RemovePartHandler &handler ) handler.add_item_or_charges( dest, i, true ); } } - refresh( false ); + refresh( &handler.get_map_ref(), false ); coeff_air_changed = true; return shift_if_needed( handler.get_map_ref() ); } @@ -2150,7 +2158,7 @@ bool vehicle::do_remove_part_actual() get_items( vp ).clear(); } if( vp.is_real_or_active_fake() ) { - const tripoint_bub_ms pt = bub_part_pos( vp ); + const tripoint_bub_ms pt = bub_part_pos( &here, vp ); here.clear_vehicle_point_from_cache( this, pt ); } it = parts.erase( it ); @@ -2165,7 +2173,7 @@ void vehicle::part_removal_cleanup() remove_fake_parts( false ); const bool changed = do_remove_part_actual(); if( changed || parts.empty() ) { - refresh(); + refresh( &here ); if( parts.empty() ) { here.destroy_vehicle( this ); return; @@ -2178,7 +2186,7 @@ void vehicle::part_removal_cleanup() if( is_powergrid() && name == power_grid_name.translated() && part_count() == 1 ) { name = parts[0].info().name(); } - refresh( false ); // Rebuild cached indices + refresh( &here, false ); // Rebuild cached indices coeff_air_dirty = coeff_air_changed; coeff_air_changed = false; } @@ -2186,6 +2194,8 @@ void vehicle::part_removal_cleanup() bool vehicle::remove_carried_vehicle( const std::vector &carried_parts, const std::vector &racks ) { + map &here = get_map(); + if( carried_parts.empty() || racks.empty() ) { return false; } @@ -2196,7 +2206,7 @@ bool vehicle::remove_carried_vehicle( const std::vector &carried_parts, // pivot is the stack that has zeroed mount point, only it has valid axis set if( !carried_stack.empty() && carried_stack.top().mount == tripoint_rel_ms::zero ) { carried_pivot = carried_stack.top(); - pivot_pos = bub_part_pos( carried_part ); + pivot_pos = bub_part_pos( &here, carried_part ); break; } } @@ -2215,7 +2225,6 @@ bool vehicle::remove_carried_vehicle( const std::vector &carried_parts, new_dir = 180_degrees; } } - map &here = get_map(); vehicle *new_vehicle = here.add_vehicle( vehicle_prototype_none, pivot_pos, new_dir ); if( new_vehicle == nullptr ) { add_msg_debug( debugmode::DF_VEHICLE, "Unable to unload bike rack, host face %d, new_dir %d!", @@ -2444,7 +2453,7 @@ bool vehicle::split_vehicles( map &here, } } } - new_v_pos3 = bub_part_pos( parts[ split_part0 ] ); + new_v_pos3 = bub_part_pos( &here, parts[ split_part0 ] ); mnt_offset = parts[ split_part0 ].mount; new_vehicle = here.add_vehicle( vehicle_prototype_none, new_v_pos3, face.dir() ); if( new_vehicle == nullptr ) { @@ -2563,7 +2572,7 @@ bool vehicle::split_vehicles( map &here, } if( split_mounts.empty() ) { - new_vehicle->refresh(); + new_vehicle->refresh( &here ); } else { // include refresh new_vehicle->shift_parts( here, - mnt_offset ); @@ -2938,6 +2947,28 @@ std::vector vehicle::get_parts_at( const tripoint_bub_ms &pos, return res; } +// NOLINTNEXTLINE(readability-make-member-function-const) +std::vector vehicle::get_parts_at( map *here, const tripoint_bub_ms &pos, + const std::string &flag, + const part_status_flag condition ) +{ + // TODO: provide access to fake parts via argument ? + const tripoint_rel_ms relative_pos = pos - pos_bub( here ); + std::vector res; + for( const vpart_reference &vpr : get_all_parts() ) { + if( vpr.part().precalc[0] != relative_pos ) { + continue; + } + if( !vpr.part().removed && + ( flag.empty() || vpr.part().info().has_flag( flag ) ) && + ( !( condition & part_status_flag::enabled ) || vpr.part().enabled ) && + ( !( condition & part_status_flag::working ) || !vpr.part().is_broken() ) ) { + res.push_back( &vpr.part() ); + } + } + return res; +} + std::vector vehicle::get_parts_at( const tripoint_bub_ms &pos, const std::string &flag, const part_status_flag condition ) const @@ -3490,9 +3521,10 @@ Character *vehicle::get_driver() const monster *vehicle::get_monster( int p ) const { + map &here = get_map(); p = part_with_feature( p, VPFLAG_BOARDABLE, false ); if( p >= 0 ) { - return get_creature_tracker().creature_at( bub_part_pos( p ), true ); + return get_creature_tracker().creature_at( bub_part_pos( &here, p ), true ); } return nullptr; } @@ -3509,17 +3541,23 @@ tripoint_abs_omt vehicle::pos_abs_omt() const tripoint_bub_ms vehicle::pos_bub() const { - return coords::project_to(rebase_bub(sm_pos - get_map().get_abs_sub().xy()) ) + rebase_rel( pos ); + return vehicle::pos_bub( &get_map() ); } -tripoint_bub_ms vehicle::bub_part_pos( const int index ) const +tripoint_bub_ms vehicle::pos_bub( map *here ) const { - return bub_part_pos( parts[ index ] ); + return coords::project_to( rebase_bub( sm_pos - here->get_abs_sub().xy() ) ) + + rebase_rel( pos ); } -tripoint_bub_ms vehicle::bub_part_pos( const vehicle_part &pt ) const +tripoint_bub_ms vehicle::bub_part_pos( map *here, const int index ) const { - return pos_bub() + pt.precalc[ 0 ]; + return bub_part_pos( here, parts[index] ); +} + +tripoint_bub_ms vehicle::bub_part_pos( map *here, const vehicle_part &pt ) const +{ + return pos_bub( here ) + pt.precalc[0]; } tripoint_abs_ms vehicle::abs_part_pos( const int index ) const @@ -3532,10 +3570,10 @@ tripoint_abs_ms vehicle::abs_part_pos( const vehicle_part &pt ) const return pos_abs() + pt.precalc[0]; } -void vehicle::set_submap_moved(map*here, const tripoint_bub_sm &p ) +void vehicle::set_submap_moved( map *here, const tripoint_bub_sm &p ) { const point_abs_ms old_msp = pos_abs().xy(); - sm_pos = here->get_abs_sub().xy() + rebase_rel(p); + sm_pos = here->get_abs_sub().xy() + rebase_rel( p ); if( !tracking_on ) { return; } @@ -3757,7 +3795,7 @@ int vehicle::drain( const int index, int amount, bool apply_loss ) return 0; } - const int drained = pt.ammo_consume( amount, &here, bub_part_pos( pt ) ); + const int drained = pt.ammo_consume( amount, &here, bub_part_pos( &here, pt ) ); invalidate_mass(); return drained; } @@ -3842,7 +3880,7 @@ bool vehicle::can_use_rails() const bool is_wheel_on_rail = false; for( int part_index : rail_wheelcache ) { // at least one wheel should be on track - if( here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_RAIL, bub_part_pos( part_index ) ) ) { + if( here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_RAIL, bub_part_pos( &here, part_index ) ) ) { is_wheel_on_rail = true; break; } @@ -4698,9 +4736,9 @@ units::power vehicle::static_drag( bool actual ) const is_actively_towed = false; } else { map &here = get_map(); - const tripoint_abs_ms towed_tow_point = here.get_abs( bub_part_pos( tow_index ) ); - const tripoint_abs_ms tower_tow_point = here.get_abs( towing_veh->bub_part_pos( - other_tow_index ) ); + const tripoint_abs_ms towed_tow_point = here.get_abs( bub_part_pos( &here, tow_index ) ); + const tripoint_abs_ms tower_tow_point = here.get_abs( towing_veh->bub_part_pos( &here, + other_tow_index ) ); is_actively_towed = rl_dist( towed_tow_point, tower_tow_point ) >= 6; } } @@ -5208,7 +5246,7 @@ units::power vehicle::total_solar_epower() const map &here = get_map(); for( const int p : solar_panels ) { const vehicle_part &vp = parts[p]; - const tripoint_bub_ms pos = bub_part_pos( vp ); + const tripoint_bub_ms pos = bub_part_pos( &here, vp ); if( vp.is_unavailable() || !is_sm_tile_outside( here.get_abs( pos ) ) ) { continue; } @@ -5231,7 +5269,7 @@ units::power vehicle::total_wind_epower() const units::power epower = 0_W; for( const int p : wind_turbines ) { const vehicle_part &vp = parts[p]; - const tripoint_bub_ms pos = bub_part_pos( vp ); + const tripoint_bub_ms pos = bub_part_pos( &here, vp ); if( vp.is_unavailable() || !is_sm_tile_outside( here.get_abs( pos ) ) ) { continue; } @@ -5252,7 +5290,7 @@ units::power vehicle::total_water_wheel_epower() const map &here = get_map(); for( const int p : water_wheels ) { const vehicle_part &vp = parts[p]; - const tripoint_bub_ms pos = bub_part_pos( vp ); + const tripoint_bub_ms pos = bub_part_pos( &here, vp ); if( vp.is_unavailable() || !is_sm_tile_over_water( here.get_abs( pos ) ) ) { continue; } @@ -5394,7 +5432,7 @@ void vehicle::power_parts() int fuel_consumed = reactors_output_bat / efficiency; // Remainder has a chance of resulting in more fuel consumption fuel_consumed += x_in_y( reactors_output_bat % efficiency, efficiency ) ? 1 : 0; - vp.ammo_consume( fuel_consumed, &here, bub_part_pos( vp ) ); + vp.ammo_consume( fuel_consumed, &here, bub_part_pos( &here, vp ) ); reactor_working = true; delta_energy_bat += reactors_output_bat; } @@ -5838,11 +5876,11 @@ void vehicle::idle( bool on_map ) continue; } for( const emit_id &e : pt.info().emissions ) { - here.emit_field( bub_part_pos( pt ), e ); + here.emit_field( bub_part_pos( &here, pt ), e ); } for( const emit_id &e : pt.info().exhaust ) { if( exhaust_and_muffle.first == -1 ) { - here.emit_field( bub_part_pos( pt ), e ); + here.emit_field( bub_part_pos( &here, pt ), e ); } else { here.emit_field( exhaust_dest( exhaust_and_muffle.first ), e ); } @@ -5928,17 +5966,17 @@ void vehicle::slow_leak() if( fuel != fuel_type_battery && fuel != fuel_type_plutonium_cell ) { item leak( fuel, calendar::turn, qty ); here.add_item_or_charges( dest, leak ); - p.ammo_consume( qty, &here, bub_part_pos( p ) ); + p.ammo_consume( qty, &here, bub_part_pos( &here, p ) ); } else if( fuel == fuel_type_plutonium_cell ) { if( p.ammo_remaining() >= PLUTONIUM_CHARGES / 10 ) { item leak( itype_plut_slurry_dense, calendar::turn, qty ); here.add_item_or_charges( dest, leak ); - p.ammo_consume( qty * PLUTONIUM_CHARGES / 10, &here, bub_part_pos( p ) ); + p.ammo_consume( qty * PLUTONIUM_CHARGES / 10, &here, bub_part_pos( &here, p ) ); } else { - p.ammo_consume( p.ammo_remaining(), &here, bub_part_pos( p ) ); + p.ammo_consume( p.ammo_remaining(), &here, bub_part_pos( &here, p ) ); } } else { - p.ammo_consume( qty, &here, bub_part_pos( p ) ); + p.ammo_consume( qty, &here, bub_part_pos( &here, p ) ); } } } @@ -6013,6 +6051,7 @@ int vehicle::add_charges( vehicle_part &vp, const item &itm ) std::optional vehicle::add_item( vehicle_part &vp, const item &itm ) { + map &here = get_map(); // const int max_weight = ?! // TODO: weight limit, calculation per vpart & vehicle stats, not a hard user limit. // add creaking sounds and damage to overloaded vpart, outright break it past a certain point, or when hitting bumps etc if( vp.is_broken() ) { @@ -6031,13 +6070,13 @@ std::optional vehicle::add_item( vehicle_part &vp, cons return std::nullopt; // @add_charges should be used in the latter case } if( charge ) { - item *here = istack.stacks_with( itm ); - if( here ) { + item *item_ptr = istack.stacks_with( itm ); + if( item_ptr ) { invalidate_mass(); - if( !here->merge_charges( itm ) ) { + if( !item_ptr->merge_charges( itm ) ) { return std::nullopt; } else { - return std::optional( istack.get_iterator_from_pointer( here ) ); + return std::optional( istack.get_iterator_from_pointer( item_ptr ) ); } } } @@ -6047,7 +6086,7 @@ std::optional vehicle::add_item( vehicle_part &vp, cons if( itm_copy.is_bucket_nonempty() ) { // this is a vehicle, so there is only one pocket. // so if it will spill, spill all of it - itm_copy.spill_contents( bub_part_pos( vp ) ); + itm_copy.spill_contents( bub_part_pos( &here, vp ) ); } const vehicle_stack::iterator new_pos = vp.items.insert( itm_copy ); @@ -6279,7 +6318,7 @@ bool vehicle::decrement_summon_timer() map &here = get_map(); for( const vpart_reference &vpr : get_all_parts() ) { vehicle_part &vp = vpr.part(); - const tripoint_bub_ms pos = bub_part_pos( vp ); + const tripoint_bub_ms pos = bub_part_pos( &here, vp ); for( item &it : vp.items ) { here.add_item_or_charges( pos, it ); } @@ -6309,6 +6348,7 @@ void vehicle::suspend_refresh() void vehicle::enable_refresh() { + map &here = get_map(); // force all caches to recalculate no_refresh = false; mass_dirty = true; @@ -6318,7 +6358,7 @@ void vehicle::enable_refresh() coeff_air_dirty = true; coeff_water_dirty = true; coeff_air_changed = true; - refresh(); + refresh( &here ); } void vehicle::refresh_active_item_cache() @@ -6338,7 +6378,7 @@ void vehicle::refresh_active_item_cache() * Refreshes all caches and refinds all parts. Used after the vehicle has had a part added or removed. * Makes indices of different part types so they're easy to find. Also calculates power drain. */ -void vehicle::refresh( const bool remove_fakes ) +void vehicle::refresh( map *here, const bool remove_fakes ) { if( no_refresh ) { return; @@ -6514,7 +6554,7 @@ void vehicle::refresh( const bool remove_fakes ) } else if( !camera_on && vpi.has_flag( "CAMERA" ) ) { vp.part().enabled = false; } - if( vpi.has_flag( "TURRET" ) && !has_part( bub_part_pos( vp.part() ), "TURRET_CONTROLS" ) ) { + if( vpi.has_flag( "TURRET" ) && !has_part( bub_part_pos( here, vp.part() ), "TURRET_CONTROLS" ) ) { vp.part().enabled = false; } if( vpi.has_flag( "MUFFLER" ) ) { @@ -6842,9 +6882,9 @@ void vehicle::do_towing_move() return; } map &here = get_map(); - const tripoint_abs_ms tower_tow_point = here.get_abs( bub_part_pos( tow_index ) ); + const tripoint_abs_ms tower_tow_point = here.get_abs( bub_part_pos( &here, tow_index ) ); const tripoint_abs_ms towed_tow_point = here.get_abs( towed_veh->bub_part_pos( - other_tow_index ) ); + &here, other_tow_index ) ); // same as above, but where the pulling vehicle is pulling from units::angle towing_veh_angle = towed_veh->get_angle_from_targ( tower_tow_point ); const bool reverse = towed_veh->tow_data.tow_direction == TOW_BACK; @@ -6907,11 +6947,11 @@ bool vehicle::is_external_part( map *here, const tripoint_bub_ms &part_pt ) cons return false; } -bool vehicle::is_external_part(const point_rel_ms& mount) const +bool vehicle::is_external_part( const point_rel_ms &mount ) const { - for (int x = -1; x <= 1; x++) { - for (int y = -1; y <= 1; y++) { - if (part_at(mount + point_rel_ms(x, y))) { + for( int x = -1; x <= 1; x++ ) { + for( int y = -1; y <= 1; y++ ) { + if( part_at( mount + point_rel_ms( x, y ) ) ) { return true; } } @@ -6999,6 +7039,7 @@ bool towing_data::set_towing( vehicle *tower_veh, vehicle *towed_veh ) void vehicle::invalidate_towing( bool first_vehicle, Character *remover ) { + map &here = get_map(); if( !is_towing() && !is_towed() ) { return; } @@ -7017,7 +7058,7 @@ void vehicle::invalidate_towing( bool first_vehicle, Character *remover ) vehicle_part &vp = parts[tow_cable_idx]; item drop = part_to_item( vp ); drop.set_damage( 0 ); - tripoint_bub_ms drop_pos = bub_part_pos( vp ); + tripoint_bub_ms drop_pos = bub_part_pos( &here, vp ); remove_part( vp ); if( other_tow_cable_idx > -1 ) { drop.reset_link( false ); @@ -7041,7 +7082,7 @@ void vehicle::invalidate_towing( bool first_vehicle, Character *remover ) put_into_vehicle_or_drop( *remover, item_drop_reason::deliberate, drops ); } } else { - get_map().add_item_or_charges( drop_pos, drop ); + here.add_item_or_charges( drop_pos, drop ); } } tow_data.clear_towing(); @@ -7066,8 +7107,7 @@ bool vehicle::tow_cable_too_far() const debugmsg( "towing data exists but no towing part" ); return false; } - map &here = get_map(); - tripoint_abs_ms towing_point = here.get_abs( bub_part_pos( index ) ); + tripoint_abs_ms towing_point = abs_part_pos( index ); if( !tow_data.get_towed_by()->tow_data.get_towed() ) { debugmsg( "vehicle %s has data for a towing vehicle, but that towing vehicle does not have %s listed as towed", disp_name(), disp_name() ); @@ -7078,8 +7118,8 @@ bool vehicle::tow_cable_too_far() const debugmsg( "towing data exists but no towing part" ); return false; } - tripoint_abs_ms towed_point = here.get_abs( tow_data.get_towed_by()->bub_part_pos( - other_index ) ); + tripoint_abs_ms towed_point = tow_data.get_towed_by()->abs_part_pos( + other_index ); if( towing_point == tripoint_abs_ms::zero || towed_point == tripoint_abs_ms::zero ) { debugmsg( "towing data exists but no towing part" ); return false; @@ -7099,8 +7139,7 @@ bool vehicle::no_towing_slack() const debugmsg( "towing data exists but no towing part" ); return false; } - map &here = get_map(); - tripoint_abs_ms towing_point = here.get_abs( bub_part_pos( index ) ); + tripoint_abs_ms towing_point = abs_part_pos( index ); if( !tow_data.get_towed()->tow_data.get_towed_by() ) { debugmsg( "vehicle %s has data for a towed vehicle, but that towed vehicle does not have %s listed as tower", disp_name(), disp_name() ); @@ -7111,7 +7150,7 @@ bool vehicle::no_towing_slack() const debugmsg( "towing data exists but no towing part" ); return false; } - tripoint_abs_ms towed_point = here.get_abs( tow_data.get_towed()->bub_part_pos( other_index ) ); + tripoint_abs_ms towed_point = tow_data.get_towed()->abs_part_pos( other_index ); if( towing_point == tripoint_abs_ms::zero || towed_point == tripoint_abs_ms::zero ) { debugmsg( "towing data exists but no towing part" ); return false; @@ -7125,7 +7164,7 @@ std::optional vehicle::get_remote_part( const vehicle_part &vp_ vehicle *veh = find_vehicle( vp_local.target.second ); // If the target vehicle is still there, ask it to remove its part if( veh != nullptr ) { - const tripoint_abs_ms local_abs = get_map().get_abs( bub_part_pos( vp_local ) ); + const tripoint_abs_ms local_abs = abs_part_pos( vp_local ); for( const int remote_partnum : veh->loose_parts ) { if( veh->parts[remote_partnum].target.first == local_abs && veh->parts[remote_partnum].info().has_flag( VPFLAG_POWER_TRANSFER ) ) { @@ -7165,13 +7204,13 @@ void vehicle::shed_loose_parts( const trinary shed_cables, const tripoint_bub_ms // Skip cables if we're only calling shed_loose_parts to remove parts with UNMOUNT_ON_MOVE. continue; } - tripoint_abs_ms vp_loose_dst = here.get_abs( dst ? *dst + vp_loose.precalc[1] : bub_part_pos( - vp_loose ) ); + tripoint_abs_ms vp_loose_dst = dst ? here.get_abs( *dst + vp_loose.precalc[1] ) : abs_part_pos( + vp_loose ); const int distance = rl_dist( vp_loose_dst, vp_loose.target.first ); const int max_dist = vp_loose.get_base().max_link_length(); if( distance > max_dist || shed_cables == trinary::ALL ) { - add_msg_if_player_sees( bub_part_pos( vp_loose ), m_warning, + add_msg_if_player_sees( bub_part_pos( &here, vp_loose ), m_warning, _( "The %s's %s was detached!" ), name, vp_loose.name( false ) ); remove_remote = true; } else { @@ -7186,7 +7225,7 @@ void vehicle::shed_loose_parts( const trinary shed_cables, const tripoint_bub_ms } const item drop = part_to_item( vp_loose ); if( !magic ) { - here.add_item_or_charges( bub_part_pos( vp_loose ), drop ); + here.add_item_or_charges( bub_part_pos( &here, vp_loose ), drop ); } if( remove_remote ) { @@ -7310,7 +7349,7 @@ void vehicle::unboard_all() const map &here = get_map(); std::vector bp = boarded_parts(); for( const int &i : bp ) { - here.unboard_vehicle( bub_part_pos( i ) ); + here.unboard_vehicle( bub_part_pos( &here, i ) ); } } @@ -7445,7 +7484,7 @@ void vehicle::shift_parts( map &here, const point_rel_ms &delta ) loot_zones = new_zones; pivot_anchor[0] -= delta.raw(); - refresh(); + refresh( &here ); //Need to also update the map after this here.rebuild_vehicle_level_caches(); } @@ -7468,7 +7507,7 @@ bool vehicle::shift_if_needed( map &here ) && !vp.has_feature( "PROTRUSION" ) && !vp.part().removed ) { shift_parts( here, vp.mount_pos() ); - refresh(); + refresh( &here ); return true; } } @@ -7476,7 +7515,7 @@ bool vehicle::shift_if_needed( map &here ) for( const vpart_reference &vp : get_all_parts() ) { if( !vp.part().removed ) { shift_parts( here, vp.mount_pos() ); - refresh(); + refresh( &here ); return true; } } @@ -7492,7 +7531,7 @@ int vehicle::break_off( map &here, vehicle_part &vp, int dmg ) if( rng( 0, vpi.durability / 10 ) >= dmg ) { return dmg; } - const tripoint_bub_ms pos = bub_part_pos( vp ); + const tripoint_bub_ms pos = bub_part_pos( &here, 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 @@ -7610,6 +7649,7 @@ int vehicle::break_off( map &here, vehicle_part &vp, int dmg ) bool vehicle::explode_fuel( vehicle_part &vp, const damage_type_id &type ) { + map &here = get_map(); const itype_id &ft = vp.info().fuel_type; item fuel = item( ft ); if( !fuel.has_explosion_data() ) { @@ -7627,7 +7667,7 @@ bool vehicle::explode_fuel( vehicle_part &vp, const damage_type_id &type ) get_event_bus().send( name ); const int pow = 120 * ( 1 - std::exp( data.explosion_factor / -5000 * ( vp.ammo_remaining() * data.fuel_size_factor ) ) ); - explosion_handler::explosion( nullptr, bub_part_pos( vp ), pow, 0.7, data.fiery_explosion ); + explosion_handler::explosion( nullptr, bub_part_pos( &here, vp ), pow, 0.7, data.fiery_explosion ); mod_hp( vp, -vp.hp() ); vp.ammo_unset(); } @@ -7641,7 +7681,7 @@ int vehicle::damage_direct( map &here, vehicle_part &vp, int dmg, const damage_t return dmg; // part is already dead } const vpart_info &vpi = vp.info(); - const tripoint_bub_ms vppos = bub_part_pos( vp ); + const tripoint_bub_ms vppos = bub_part_pos( &here, vp ); // If auto-driving and damage happens, bail out if( is_autodriving ) { stop_autodriving(); @@ -7690,7 +7730,7 @@ int vehicle::damage_direct( map &here, vehicle_part &vp, int dmg, const damage_t } // refresh cache in case the broken part has changed the status // do not remove fakes parts in case external vehicle part references get invalidated - refresh( false ); + refresh( &here, false ); } if( vp.is_fuel_store() ) { @@ -7737,7 +7777,7 @@ void vehicle::leak_fuel( vehicle_part &pt ) const map &here = get_map(); // leak in random directions but prefer closest tiles and avoid walls or other obstacles - std::vector tiles = closest_points_first( bub_part_pos( pt ), 1 ); + std::vector tiles = closest_points_first( bub_part_pos( &here, pt ), 1 ); tiles.erase( std::remove_if( tiles.begin(), tiles.end(), [&here]( const tripoint_bub_ms & e ) { return !here.passable( e ); } ), tiles.end() ); @@ -7746,7 +7786,7 @@ void vehicle::leak_fuel( vehicle_part &pt ) const const itype *fuel = item::find_type( pt.ammo_current() ); while( !tiles.empty() && pt.ammo_remaining() ) { int qty = pt.ammo_consume( rng( 0, std::max( pt.ammo_remaining() / 3, 1 ) ), - &here, bub_part_pos( pt ) ); + &here, bub_part_pos( &here, pt ) ); if( qty > 0 ) { here.add_item_or_charges( random_entry( tiles ), item( fuel, calendar::turn, qty ) ); } @@ -7859,6 +7899,7 @@ item vehicle::get_folded_item() const bool vehicle::restore_folded_parts( const item &it ) { + map &here = get_map(); const JsonValue jv_parts = json_loader::from_string( it.get_var( "folded_parts" ) ); deserialize_parts( static_cast( jv_parts ) ); @@ -7900,7 +7941,7 @@ bool vehicle::restore_folded_parts( const item &it ) } } - refresh(); + refresh( &here ); face.init( 0_degrees ); turn_dir = 0_degrees; turn( 0_degrees ); @@ -8031,7 +8072,8 @@ point_rel_ms vpart_position::mount_pos() const tripoint_bub_ms vpart_position::pos_bub() const { - return vehicle().bub_part_pos( part_index() ); + map &here = get_map(); + return vehicle().bub_part_pos( &here, part_index() ); } bool vpart_reference::has_feature( const std::string &f ) const @@ -8123,7 +8165,7 @@ void vehicle::update_time( const time_point &update_to ) const vehicle_part &pt = parts[idx]; // we need an unbroken funnel mounted on the exterior of the vehicle - if( pt.is_unavailable() || !is_sm_tile_outside( here.get_abs( bub_part_pos( pt ) ) ) ) { + if( pt.is_unavailable() || !is_sm_tile_outside( abs_part_pos( pt ) ) ) { continue; } @@ -8160,7 +8202,7 @@ void vehicle::update_time( const time_point &update_to ) units::power epower = 0_W; for( const int p : solar_panels ) { const vehicle_part &vp = parts[p]; - const tripoint_bub_ms pos = bub_part_pos( vp ); + const tripoint_bub_ms pos = bub_part_pos( &here, vp ); if( vp.is_unavailable() || !is_sm_tile_outside( here.get_abs( pos ) ) ) { continue; } @@ -8471,7 +8513,6 @@ item vehicle::removed_part( const vehicle_part &vp ) const bool vehicle::refresh_zones() { if( zones_dirty ) { - map &here = get_map(); decltype( loot_zones ) new_zones; for( auto const &z : loot_zones ) { zone_data zone = z.second; @@ -8486,7 +8527,7 @@ bool vehicle::refresh_zones() // By continuing here and not adding to new_zones, we effectively remove it continue; } - tripoint_abs_ms zone_pos = here.get_abs( bub_part_pos( part_idx ) ); + tripoint_abs_ms zone_pos = abs_part_pos( part_idx ); //Set the position of the zone to that part zone.set_position( std::pair( zone_pos, zone_pos ), false, false, true ); diff --git a/src/vehicle.h b/src/vehicle.h index daa699291dba8..7be077b321f1f 100644 --- a/src/vehicle.h +++ b/src/vehicle.h @@ -911,7 +911,7 @@ class vehicle void suspend_refresh(); void enable_refresh(); //Refresh all caches and re-locate all parts - void refresh( bool remove_fakes = true ); + void refresh( map *here, bool remove_fakes = true ); // Refresh active_item cache for vehicle parts void refresh_active_item_cache(); @@ -971,7 +971,7 @@ class vehicle bool has_tow_attached() const; int get_tow_part() const; bool is_external_part( map *here, const tripoint_bub_ms &part_pt ) const; - bool is_external_part(const point_rel_ms& mount) const; + bool is_external_part( const point_rel_ms &mount ) const; bool is_towed() const; void set_tow_directions(); /// @return true if vehicle is an appliance @@ -1289,8 +1289,12 @@ class vehicle * @param flag if set only flags with this part will be considered * @param condition enum to include unabled, unavailable, and broken parts */ + // TODO: Get rid of map less overload. std::vector get_parts_at( const tripoint_bub_ms &pos, const std::string &flag, part_status_flag condition ); + std::vector get_parts_at( map *here, const tripoint_bub_ms &pos, + const std::string &flag, + part_status_flag condition ); std::vector get_parts_at( const tripoint_bub_ms &pos, const std::string &flag, part_status_flag condition ) const; @@ -1434,12 +1438,14 @@ class vehicle tripoint_abs_omt pos_abs_omt() const; // Returns the coordinates (in map squares) of the vehicle relative to the local map. // Warning: Don't assume this position contains a vehicle part + // TODO: Replace usage of map less version. tripoint_bub_ms pos_bub() const; + tripoint_bub_ms pos_bub( map *here ) const; /** * Get the coordinates of the studied part of the vehicle */ - tripoint_bub_ms bub_part_pos( int index ) const; - tripoint_bub_ms bub_part_pos( const vehicle_part &pt ) const; + tripoint_bub_ms bub_part_pos( map *here, int index ) const; + tripoint_bub_ms bub_part_pos( map *here, const vehicle_part &pt ) const; tripoint_abs_ms abs_part_pos( int index ) const; tripoint_abs_ms abs_part_pos( const vehicle_part &pt ) const; /** diff --git a/src/vehicle_move.cpp b/src/vehicle_move.cpp index a03d351740574..bfe529416149d 100644 --- a/src/vehicle_move.cpp +++ b/src/vehicle_move.cpp @@ -2014,7 +2014,7 @@ bool vehicle::level_vehicle() if( prt.info().location != part_location_structure ) { continue; } - const tripoint_bub_ms part_pos = bub_part_pos( prt ); + const tripoint_bub_ms part_pos = bub_part_pos( &here, prt ); if( no_support.find( part_pos.z() ) == no_support.end() ) { no_support[part_pos.z()] = part_pos.z() > -OVERMAP_DEPTH; } @@ -2043,7 +2043,7 @@ bool vehicle::level_vehicle() adjust_level = true; // drop unsupported parts 1 zlevel for( size_t prt = 0; prt < parts.size(); prt++ ) { - if( bub_part_pos( prt ).z() == zlevel ) { + if( abs_part_pos( prt ).z() == zlevel ) { dropped_parts.insert( static_cast( prt ) ); } } @@ -2090,7 +2090,7 @@ void vehicle::check_falling_or_floating() // Check under the wheels, if they're supported nothing else matters. int supported_wheels = 0; for( int wheel_index : wheelcache ) { - const tripoint_bub_ms position = bub_part_pos( wheel_index ); + const tripoint_bub_ms position = bub_part_pos( &here, wheel_index ); if( has_support( position, false ) ) { ++supported_wheels; } @@ -2132,7 +2132,7 @@ void vehicle::check_falling_or_floating() in_water = 2 * water_tiles >= pts.size(); } -float map::vehicle_wheel_traction( const vehicle &veh, bool ignore_movement_modifiers ) const +float map::vehicle_wheel_traction( const vehicle &veh, bool ignore_movement_modifiers ) { if( veh.is_in_water( /* deep_water = */ true ) ) { return veh.can_float() ? 1.0f : -1.0f; @@ -2151,7 +2151,7 @@ float map::vehicle_wheel_traction( const vehicle &veh, bool ignore_movement_modi for( const int wheel_idx : veh.wheelcache ) { const vehicle_part &vp = veh.part( wheel_idx ); const vpart_info &vpi = vp.info(); - const tripoint_bub_ms pp = veh.bub_part_pos( vp ); + const tripoint_bub_ms pp = veh.bub_part_pos( this, vp ); const ter_t &tr = ter( pp ).obj(); if( tr.has_flag( ter_furn_flag::TFLAG_DEEP_WATER ) || tr.has_flag( ter_furn_flag::TFLAG_NO_FLOOR ) ) { @@ -2193,6 +2193,7 @@ float map::vehicle_wheel_traction( const vehicle &veh, bool ignore_movement_modi units::angle map::shake_vehicle( vehicle &veh, const int velocity_before, const units::angle &direction ) { + map &here = get_map(); const int d_vel = std::abs( veh.velocity - velocity_before ) / 100; std::vector riders = veh.get_riders(); @@ -2206,7 +2207,7 @@ units::angle map::shake_vehicle( vehicle &veh, const int velocity_before, continue; } - const tripoint_bub_ms part_pos = veh.bub_part_pos( ps ); + const tripoint_bub_ms part_pos = veh.bub_part_pos( &here, ps ); if( rider->pos_bub() != part_pos ) { debugmsg( "throw passenger: passenger at %d,%d,%d, part at %d,%d,%d", rider->posx(), rider->posy(), rider->posz(), diff --git a/src/vehicle_use.cpp b/src/vehicle_use.cpp index f101f82cdb09f..ea16813ba92dc 100644 --- a/src/vehicle_use.cpp +++ b/src/vehicle_use.cpp @@ -137,6 +137,8 @@ void handbrake() void vehicle::control_doors() { + map &here = get_map(); + const auto open_or_close_all = [this]( bool new_open, const std::string & require_flag ) { for( const vpart_reference &vpr_motor : get_avail_parts( "DOOR_MOTOR" ) ) { const int motorized_idx = new_open @@ -170,7 +172,7 @@ void vehicle::control_doors() } }; - const auto add_openable = [this]( veh_menu & menu, int vp_idx ) { + const auto add_openable = [this, &here]( veh_menu & menu, int vp_idx ) { if( vp_idx == -1 ) { return; } @@ -179,7 +181,7 @@ void vehicle::control_doors() const bool open = !vp.open; menu.add( string_format( "%s %s", actname, vp.name() ) ) .hotkey_auto() - .location( bub_part_pos( vp ).raw() ) + .location( bub_part_pos( &here, vp ).raw() ) .keep_menu_open() .on_submit( [this, vp_idx, open] { if( can_close( vp_idx, get_player_character() ) ) @@ -189,7 +191,7 @@ void vehicle::control_doors() } ); }; - const auto add_lockable = [this]( veh_menu & menu, int vp_idx ) { + const auto add_lockable = [this, &here]( veh_menu & menu, int vp_idx ) { if( vp_idx == -1 ) { return; } @@ -198,7 +200,7 @@ void vehicle::control_doors() const bool lock = !vp.locked; menu.add( string_format( "%s %s", actname, vp.name() ) ) .hotkey_auto() - .location( bub_part_pos( vp ).raw() ) + .location( bub_part_pos( &here, vp ).raw() ) .keep_menu_open() .on_submit( [this, vp_idx, lock] { lock_or_unlock( vp_idx, lock ); @@ -555,7 +557,8 @@ void vehicle::toggle_tracking() } } -void vehicle::connect( map *here, const tripoint_bub_ms &source_pos, const tripoint_bub_ms &target_pos ) +void vehicle::connect( map *here, const tripoint_bub_ms &source_pos, + const tripoint_bub_ms &target_pos ) { const optional_vpart_position sel_vp = here->veh_at( target_pos ); const optional_vpart_position prev_vp = here->veh_at( source_pos ); @@ -575,11 +578,13 @@ void vehicle::connect( map *here, const tripoint_bub_ms &source_pos, const tripo double vehicle::engine_cold_factor( const vehicle_part &vp ) const { + map &here = get_map(); + if( !vp.info().has_flag( "E_COLD_START" ) ) { return 0.0; } - const tripoint_bub_ms pos = bub_part_pos( vp ); + const tripoint_bub_ms pos = bub_part_pos( &here, vp ); double eff_temp = units::to_fahrenheit( get_weather().get_temperature( pos ) ); if( !vp.has_fault_flag( "BAD_COLD_START" ) ) { eff_temp = std::min( eff_temp, 20.0 ); @@ -629,6 +634,8 @@ bool vehicle::auto_select_fuel( vehicle_part &vp ) bool vehicle::start_engine( vehicle_part &vp ) { + map &here = get_map(); + const vpart_info &vpi = vp.info(); if( !is_engine_on( vp ) ) { return false; @@ -669,7 +676,7 @@ bool vehicle::start_engine( vehicle_part &vp ) const double dmg = vp.damage_percent(); const time_duration start_time = engine_start_time( vp ); - const tripoint_bub_ms pos = bub_part_pos( vp ); + const tripoint_bub_ms pos = bub_part_pos( &here, vp ); if( ( 1 - dmg ) < vpi.engine_info->backfire_threshold && one_in( vpi.engine_info->backfire_freq ) ) { @@ -746,6 +753,7 @@ bool vehicle::start_engine( vehicle_part &vp ) void vehicle::stop_engines() { + map &here = get_map(); vehicle_noise = 0; engine_on = false; for( const int p : engines ) { @@ -754,7 +762,8 @@ void vehicle::stop_engines() continue; } - sounds::sound( bub_part_pos( vp ), 2, sounds::sound_t::movement, _( "the engine go silent" ) ); + sounds::sound( bub_part_pos( &here, vp ), 2, sounds::sound_t::movement, + _( "the engine go silent" ) ); std::string variant = vp.info().id.str(); @@ -773,11 +782,13 @@ void vehicle::stop_engines() sfx::play_variant_sound( "engine_stop", variant, vp.info().engine_info->noise_factor ); } sfx::do_vehicle_engine_sfx(); - refresh(); + refresh( &here ); } void vehicle::start_engines( Character *driver, const bool take_control, const bool autodrive ) { + map &here = get_map(); + bool has_engine = std::any_of( engines.begin(), engines.end(), [&]( int idx ) { return parts[ idx ].enabled && !parts[ idx ].is_broken(); } ); @@ -797,7 +808,7 @@ void vehicle::start_engines( Character *driver, const bool take_control, const b for( const int p : engines ) { const vehicle_part &vp = parts[p]; if( !has_starting_engine_position && !vp.is_broken() && vp.enabled ) { - starting_engine_position = bub_part_pos( vp ); + starting_engine_position = bub_part_pos( &here, vp ); has_starting_engine_position = true; } has_engine = has_engine || is_engine_on( vp ); @@ -810,7 +821,7 @@ void vehicle::start_engines( Character *driver, const bool take_control, const b if( !has_engine ) { add_msg( m_info, _( "The %s doesn't have an engine!" ), name ); - refresh(); + refresh( &here ); return; } @@ -823,7 +834,7 @@ void vehicle::start_engines( Character *driver, const bool take_control, const b driver->activity.relative_placement = starting_engine_position - driver->pos_bub(); driver->activity.values.push_back( take_control ); } - refresh(); + refresh( &here ); } void vehicle::enable_patrol() @@ -1115,12 +1126,12 @@ void vehicle::operate_scoop() _( "Whirrrr" ), _( "Ker-chunk" ), _( "Swish" ), _( "Cugugugugug" ) } }; - sounds::sound( bub_part_pos( scoop ), rng( 20, 35 ), sounds::sound_t::combat, + sounds::sound( bub_part_pos( &here, scoop ), rng( 20, 35 ), sounds::sound_t::combat, random_entry_ref( sound_msgs ), false, "vehicle", "scoop" ); std::vector parts_points; parts_points.reserve( 8 ); for( const tripoint_bub_ms ¤t : - here.points_in_radius( bub_part_pos( scoop ), 1 ) ) { + here.points_in_radius( bub_part_pos( &here, scoop ), 1 ) ) { parts_points.push_back( current ); } for( const tripoint_bub_ms &position : parts_points ) { @@ -1260,7 +1271,7 @@ bool vehicle::can_close( int part_index, Character &who ) for( int partID : vec ) { // Check the part for collisions, then if there's a fake part present check that too. while( partID >= 0 ) { - const Creature *const mon = creatures.creature_at( bub_part_pos( parts[partID] ) ); + const Creature *const mon = creatures.creature_at( abs_part_pos( parts[partID] ) ); if( mon ) { if( mon->is_avatar() ) { who.add_msg_if_player( m_info, _( "There's some buffoon in the way!" ) ); diff --git a/tests/vehicle_export_test.cpp b/tests/vehicle_export_test.cpp index 7aa038e62ba85..d8a9f5521450b 100644 --- a/tests/vehicle_export_test.cpp +++ b/tests/vehicle_export_test.cpp @@ -33,6 +33,7 @@ static bool operator==( const vehicle_item_spawn &l, const vehicle_item_spawn &r TEST_CASE( "export_vehicle_test" ) { clear_map(); + map &here = get_map(); // Spawn the vehicle with fuel. vehicle *veh_ptr = get_map().add_vehicle( vehicle_prototype_veh_export_test, tripoint_bub_ms::zero, 0_degrees, -1, 0 ); @@ -40,8 +41,8 @@ TEST_CASE( "export_vehicle_test" ) // To ensure the zones get placed. veh_ptr->set_owner( get_player_character() ); - veh_ptr->place_zones( get_map() ); - veh_ptr->refresh(); + veh_ptr->place_zones( here ); + veh_ptr->refresh( &here ); veh_ptr->refresh_zones(); std::ostringstream os; diff --git a/tests/vehicle_fake_part_test.cpp b/tests/vehicle_fake_part_test.cpp index c9519ce3210e5..a451251f43889 100644 --- a/tests/vehicle_fake_part_test.cpp +++ b/tests/vehicle_fake_part_test.cpp @@ -333,7 +333,7 @@ TEST_CASE( "vehicle_with_fake_obstacle_parts_block_movement", "[vehicle][vehicle vehicle *veh = here.add_vehicle( vehicle_prototype_obstacle_test, test_origin, 315_degrees, 100, 0 ); REQUIRE( veh != nullptr ); - veh->refresh(); + veh->refresh( &here ); here.set_seen_cache_dirty( 0 ); here.build_map_cache( 0 ); validate_part_count( *veh, 0, 315_degrees, 11, 6, 5 ); diff --git a/tests/vehicle_power_test.cpp b/tests/vehicle_power_test.cpp index d353a01a04703..9d96b1fa153b4 100644 --- a/tests/vehicle_power_test.cpp +++ b/tests/vehicle_power_test.cpp @@ -95,7 +95,7 @@ TEST_CASE( "power_loss_to_cables", "[vehicle][power]" ) REQUIRE( frame_part_idx != -1 ); const int bat_part_idx = veh->install_part( point_rel_ms::zero, vpart_small_storage_battery ); REQUIRE( bat_part_idx != -1 ); - veh->refresh(); + veh->refresh( &here ); here.add_vehicle_to_cache( veh ); batteries.emplace_back( *veh, bat_part_idx ); } diff --git a/tests/vehicle_ramp_test.cpp b/tests/vehicle_ramp_test.cpp index 09ee4854c7151..2447a5cc68665 100644 --- a/tests/vehicle_ramp_test.cpp +++ b/tests/vehicle_ramp_test.cpp @@ -280,7 +280,7 @@ static void level_out( const vproto_id &veh_id, const bool drop_pos ) } std::set z_span; for( vehicle_part *prt : all_parts ) { - z_span.insert( veh.bub_part_pos( *prt ).z() ); + z_span.insert( veh.abs_part_pos( *prt ).z() ); } REQUIRE( z_span.size() > 1 ); @@ -306,7 +306,7 @@ static void level_out( const vproto_id &veh_id, const bool drop_pos ) here.vehmove(); for( vehicle_part *prt : all_parts ) { - CHECK( veh.bub_part_pos( *prt ).z() == 0 ); + CHECK( veh.abs_part_pos( *prt ).z() == 0 ); } CHECK( dmon.posz() == 0 ); CHECK( veh.pos_bub().z() == 0 ); diff --git a/tests/vehicle_test.cpp b/tests/vehicle_test.cpp index bdc2623de9912..f27e1018b731f 100644 --- a/tests/vehicle_test.cpp +++ b/tests/vehicle_test.cpp @@ -591,7 +591,7 @@ static void rack_check( const rack_preset &preset ) vehicle *veh_ptr = m.add_vehicle( preset.vehicles[i], preset.positions[i], preset.facings[i], 0, 0 ); REQUIRE( veh_ptr != nullptr ); - veh_ptr->refresh(); + veh_ptr->refresh( &m ); vehs.push_back( veh_ptr ); veh_names.push_back( veh_ptr->name ); } @@ -743,13 +743,13 @@ static int test_autopilot_moving( const vproto_id &veh_id, const vpart_id &extra { clear_avatar(); clear_map(); + map &here = get_map(); Character &player_character = get_player_character(); // Move player somewhere safe REQUIRE_FALSE( player_character.in_vehicle ); player_character.setpos( tripoint_bub_ms::zero ); const tripoint_bub_ms map_starting_point( 60, 60, 0 ); - map &here = get_map(); vehicle *veh_ptr = here.add_vehicle( veh_id, map_starting_point, -90_degrees, 100, 0, false ); REQUIRE( veh_ptr != nullptr ); @@ -765,7 +765,7 @@ static int test_autopilot_moving( const vproto_id &veh_id, const vpart_id &extra veh.is_following = true; veh.is_patrolling = false; veh.engine_on = true; - veh.refresh(); + veh.refresh( &here ); int turns_left = 10; int tiles_travelled = 0; diff --git a/tests/vehicle_turrets_test.cpp b/tests/vehicle_turrets_test.cpp index ef4dfc9d38403..6d37bb414189a 100644 --- a/tests/vehicle_turrets_test.cpp +++ b/tests/vehicle_turrets_test.cpp @@ -100,7 +100,7 @@ TEST_CASE( "vehicle_turret", "[vehicle][gun][magazine]" ) REQUIRE( qry.query() == turret_data::status::ready ); REQUIRE( qry.range() > 0 ); - player_character.setpos( veh->bub_part_pos( vp ) ); + player_character.setpos( &here, veh->bub_part_pos( &here, vp ) ); int shots_fired = 0; // 3 attempts to fire, to account for possible misfires for( int attempt = 0; shots_fired == 0 && attempt < 3; attempt++ ) {