From 781ecc4fe0d255c2c2a46796859be9a03b97f419 Mon Sep 17 00:00:00 2001 From: scarf Date: Fri, 15 Sep 2023 15:33:53 +0900 Subject: [PATCH 1/8] refactor: flatten nested conditions --- src/iexamine.cpp | 56 ++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/src/iexamine.cpp b/src/iexamine.cpp index ae0fd466304c..ab8ff188840c 100644 --- a/src/iexamine.cpp +++ b/src/iexamine.cpp @@ -898,17 +898,23 @@ void iexamine::elevator( player &p, const tripoint &examp ) for( Creature &critter : g->all_creatures() ) { if( critter.is_player() ) { continue; - } else if( here.has_flag( flag_ELEVATOR, critter.pos() ) ) { - tripoint critter_omt = ms_to_omt_copy( here.getabs( critter.pos() ) ); - if( critter_omt == new_floor_omt ) { - for( const tripoint &candidate : closest_points_first( critter.pos(), 10 ) ) { - if( !here.has_flag( flag_ELEVATOR, candidate ) && - here.passable( candidate ) && - !g->critter_at( candidate ) ) { - critter.setpos( candidate ); - break; - } - } + } + + if( !here.has_flag( flag_ELEVATOR, critter.pos() ) ) { + continue; + } + + tripoint critter_omt = ms_to_omt_copy( here.getabs( critter.pos() ) ); + if( critter_omt != new_floor_omt ) { + continue; + } + + for( const tripoint &candidate : closest_points_first( critter.pos(), 10 ) ) { + if( !here.has_flag( flag_ELEVATOR, candidate ) && + here.passable( candidate ) && + !g->critter_at( candidate ) ) { + critter.setpos( candidate ); + break; } } } @@ -947,18 +953,22 @@ void iexamine::elevator( player &p, const tripoint &examp ) for( Creature &critter : g->all_creatures() ) { if( critter.is_player() ) { continue; - } else if( here.has_flag( flag_ELEVATOR, critter.pos() ) ) { - tripoint critter_omt = ms_to_omt_copy( here.getabs( critter.pos() ) ); - - if( critter_omt == original_floor_omt ) { - for( const tripoint &candidate : closest_points_first( p.pos(), 10 ) ) { - if( here.has_flag( flag_ELEVATOR, candidate ) && - candidate != p.pos() && - !g->critter_at( candidate ) ) { - critter.setpos( candidate ); - break; - } - } + } + + if( !here.has_flag( flag_ELEVATOR, critter.pos() ) ) { + continue; + } + + tripoint critter_omt = ms_to_omt_copy( here.getabs( critter.pos() ) ); + if( critter_omt != original_floor_omt ) { + continue; + } + + for( const tripoint &candidate : closest_points_first( p.pos(), 10 ) ) { + if( here.has_flag( flag_ELEVATOR, candidate ) && candidate != p.pos() && + !g->critter_at( candidate ) ) { + critter.setpos( candidate ); + break; } } } From 3f47c00f3558998bfc0436f985721711e080fd15 Mon Sep 17 00:00:00 2001 From: scarf Date: Sat, 16 Sep 2023 20:14:39 +0900 Subject: [PATCH 2/8] feat: utility function for point rotation --- src/point_rotate.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/point_rotate.h | 26 ++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 src/point_rotate.cpp create mode 100644 src/point_rotate.h diff --git a/src/point_rotate.cpp b/src/point_rotate.cpp new file mode 100644 index 000000000000..5f31f8f17090 --- /dev/null +++ b/src/point_rotate.cpp @@ -0,0 +1,39 @@ +#include "overmapbuffer.h" +#include "omdata.h" +#include "point.h" + +auto rotate( point p, point dim, int turns ) -> point +{ + switch( turns ) { + case 1: + return { dim.y - p.y - 1, p.x }; + case 2: + return { dim.x - p.x - 1, dim.y - p.y - 1 }; + case 3: + return { p.y, dim.x - p.x - 1 }; + default: + return p; + } +} + +auto rotate( const tripoint &p, point dim, int turns ) -> tripoint +{ + return { rotate( p.xy(), dim, turns ), p.z }; +} + +auto rotate_point_sm( const tripoint &p, const tripoint &orig, int turns ) -> tripoint +{ + const tripoint p_sm{ p - orig.xy() }; + const tripoint rd{ rotate( p_sm, { SEEX * 2, SEEY * 2 }, turns ) }; + + return tripoint{ rd + orig.xy() }; +} + +auto get_rot_delta( const tripoint_abs_omt &here, const tripoint_abs_omt &there ) -> int +{ + const auto this_dir = overmap_buffer.ter( there )->get_dir(); + const auto that_dir = overmap_buffer.ter( here )->get_dir(); + + int const diff = static_cast( this_dir ) - static_cast( that_dir ); + return diff >= 0 ? diff : 4 + diff; +} diff --git a/src/point_rotate.h b/src/point_rotate.h new file mode 100644 index 000000000000..a93706e806e0 --- /dev/null +++ b/src/point_rotate.h @@ -0,0 +1,26 @@ +#pragma once +#ifndef CATA_SRC_POINT_ROTATE_H +#define CATA_SRC_POINT_ROTATE_H + +#include "point.h" +#include "coordinates.h" + +/** + * Rotate point clockwise @param turns times, 90 degrees per turn, + * around the center of a rectangle with the dimensions specified + * by @param dim + * set dim to (0, 0) to rotate around the origin. + */ +auto rotate( point p, point dim, int turns ) -> point; + +/** + * Rotates just the x,y component of the tripoint. See point::rotate() + */ +auto rotate( const tripoint &p, point dim, int turns ) -> tripoint; + +/** works like rotate but for submaps. */ +auto rotate_point_sm( const tripoint &p, const tripoint &orig, int turns ) -> tripoint; + +auto get_rot_delta( const tripoint_abs_omt &here, const tripoint_abs_omt &there ) -> int; + +#endif // CATA_SRC_POINT_ROTATE_H From b782cee4cff76cc2c23e199a1e8b9cde3b9225f7 Mon Sep 17 00:00:00 2001 From: scarf Date: Sat, 16 Sep 2023 20:15:56 +0900 Subject: [PATCH 3/8] feat: add elevator to ter_bitflags --- src/mapdata.cpp | 1 + src/mapdata.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/mapdata.cpp b/src/mapdata.cpp index 67d295f47148..9cc15a0f7e69 100644 --- a/src/mapdata.cpp +++ b/src/mapdata.cpp @@ -194,6 +194,7 @@ static const std::unordered_map ter_bitflags_map = { { "SUSPENDED", TFLAG_SUSPENDED }, // This furniture is suspended between other terrain, and will cause a cascading failure on break. { "FRIDGE", TFLAG_FRIDGE }, // This is an active fridge. { "FREEZER", TFLAG_FREEZER }, // This is an active freezer. + { "ELEVATOR", TFLAG_ELEVATOR }, // This is an elevator. } }; diff --git a/src/mapdata.h b/src/mapdata.h index 2cc1ccc24f8b..2405ce7bd75a 100644 --- a/src/mapdata.h +++ b/src/mapdata.h @@ -324,6 +324,7 @@ enum ter_bitflags : int { TFLAG_SUSPENDED, TFLAG_FRIDGE, TFLAG_FREEZER, + TFLAG_ELEVATOR, NUM_TERFLAGS }; From 9b0985a894c99b2b1c60a3967b9a6231258860a5 Mon Sep 17 00:00:00 2001 From: scarf Date: Sat, 16 Sep 2023 20:24:26 +0900 Subject: [PATCH 4/8] feat(port): move vehicles in elevator DDA PR: https://github.com/CleverRaven/Cataclysm-DDA/pull/58840 Co-authored-by: andrei --- src/iexamine.cpp | 96 ----------------- src/iexamine_elevator.cpp | 222 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 222 insertions(+), 96 deletions(-) create mode 100644 src/iexamine_elevator.cpp diff --git a/src/iexamine.cpp b/src/iexamine.cpp index ab8ff188840c..9de8b3365be3 100644 --- a/src/iexamine.cpp +++ b/src/iexamine.cpp @@ -242,7 +242,6 @@ static const std::string flag_SPLINT( "SPLINT" ); static const std::string flag_VARSIZE( "VARSIZE" ); static const std::string flag_WALL( "WALL" ); static const std::string flag_WRITE_MESSAGE( "WRITE_MESSAGE" ); -static const std::string flag_ELEVATOR( "ELEVATOR" ); // @TODO maybe make this a property of the item (depend on volume/type) static const time_duration milling_time = 6_hours; @@ -879,101 +878,6 @@ void iexamine::toilet( player &p, const tripoint &examp ) } } -/** - * If underground, move 2 levels up else move 2 levels down. Stable movement between levels 0 and -2. - */ -void iexamine::elevator( player &p, const tripoint &examp ) -{ - map &here = get_map(); - if( !query_yn( _( "Use the %s?" ), here.tername( examp ) ) ) { - return; - } - int movez = ( examp.z < 0 ? 2 : -2 ); - - tripoint original_floor_omt = ms_to_omt_copy( here.getabs( examp ) ); - tripoint new_floor_omt = original_floor_omt + tripoint( point_zero, movez ); - - - // first find critters in the destination elevator and move them out of the way - for( Creature &critter : g->all_creatures() ) { - if( critter.is_player() ) { - continue; - } - - if( !here.has_flag( flag_ELEVATOR, critter.pos() ) ) { - continue; - } - - tripoint critter_omt = ms_to_omt_copy( here.getabs( critter.pos() ) ); - if( critter_omt != new_floor_omt ) { - continue; - } - - for( const tripoint &candidate : closest_points_first( critter.pos(), 10 ) ) { - if( !here.has_flag( flag_ELEVATOR, candidate ) && - here.passable( candidate ) && - !g->critter_at( candidate ) ) { - critter.setpos( candidate ); - break; - } - } - } - - // TODO: do we have struct or pair to indicate from -> to? - const auto move_item = [&]( map_stack & items, const tripoint & src, const tripoint & dest ) { - for( auto it = items.begin(); it != items.end(); ) { - here.add_item_or_charges( dest, *it ); - it = here.i_rem( src, it ); - } - }; - - const auto first_elevator_tile = [&]( const tripoint & pos ) -> tripoint { - for( const tripoint &candidate : closest_points_first( pos, 10 ) ) - { - if( here.has_flag( flag_ELEVATOR, candidate ) ) { - return candidate; - } - } - return pos; - }; - - // move along every item in the elevator - for( const tripoint &pos : closest_points_first( p.pos(), 10 ) ) { - if( here.has_flag( flag_ELEVATOR, pos ) ) { - map_stack items = here.i_at( pos ); - tripoint dest = first_elevator_tile( pos + tripoint( 0, 0, movez ) ); - move_item( items, pos, dest ); - } - } - - // move the player - g->vertical_move( movez, false ); - - // finally, bring along everyone who was in the elevator with the player - for( Creature &critter : g->all_creatures() ) { - if( critter.is_player() ) { - continue; - } - - if( !here.has_flag( flag_ELEVATOR, critter.pos() ) ) { - continue; - } - - tripoint critter_omt = ms_to_omt_copy( here.getabs( critter.pos() ) ); - if( critter_omt != original_floor_omt ) { - continue; - } - - for( const tripoint &candidate : closest_points_first( p.pos(), 10 ) ) { - if( here.has_flag( flag_ELEVATOR, candidate ) && candidate != p.pos() && - !g->critter_at( candidate ) ) { - critter.setpos( candidate ); - break; - } - } - } -} - /** * Open or close gate. */ diff --git a/src/iexamine_elevator.cpp b/src/iexamine_elevator.cpp new file mode 100644 index 000000000000..d5d5c23b7231 --- /dev/null +++ b/src/iexamine_elevator.cpp @@ -0,0 +1,222 @@ +#include "game.h" +#include "iexamine.h" +#include "mapdata.h" +#include "output.h" +#include "omdata.h" +#include "overmapbuffer.h" +#include "player.h" +#include "coordinates.h" +#include "map.h" +#include "point.h" +#include "ui.h" +#include "vpart_range.h" +#include "point_rotate.h" + +namespace +{ + +using elevator_tiles = std::vector; +auto get_elevator_here( const Character &you ) -> elevator_tiles +{ + const auto &here = get_map(); + const auto &points = closest_points_first( you.pos(), SEEX - 1 ); + + elevator_tiles tiles; + std::copy_if( points.begin(), points.end(), std::back_inserter( tiles ), + [&here]( const tripoint & pos ) { + return here.has_flag( TFLAG_ELEVATOR, pos ); + } ); + + return tiles; +} + +auto get_elevator_dest( const elevator_tiles &elevator_here, + const tripoint &sm_orig, + int turns, + int movez ) -> elevator_tiles +{ + elevator_tiles tiles; + std::transform( elevator_here.begin(), elevator_here.end(), std::back_inserter( tiles ), + [turns, &sm_orig, movez]( tripoint const & p ) { + return rotate_point_sm( { p.xy(), movez }, sm_orig, turns ); + } ); + + return tiles; +} + +auto choose_elevator_destz( const tripoint &examp, const tripoint_abs_omt &this_omt, + const tripoint &sm_orig ) -> int +{ + const auto this_floor = _( " (this floor)" ); + + map &here = get_map(); + uilist choice; + choice.title = _( "Select destination floor" ); + for( int z = OVERMAP_HEIGHT; z >= -OVERMAP_DEPTH; z-- ) { + const tripoint_abs_omt that_omt{ this_omt.xy(), z }; + const int delta = get_rot_delta( this_omt, that_omt ); + const tripoint zp = + rotate_point_sm( { examp.xy(), z }, sm_orig, delta ); + + if( here.ter( zp )->examine == &iexamine::elevator ) { + const std::string omt_name = overmap_buffer.ter_existing( that_omt )->get_name(); + const auto floor_name = z == examp.z ? this_floor : ""; + const std::string name = string_format( "%3iF %s%s", z, omt_name, floor_name ); + + choice.addentry( z, z != examp.z, MENU_AUTOASSIGN, name ); + } + } + choice.query(); + return choice.ret; +} + +} // namespace + +namespace +{ + +enum class overlap_status { outside, inside, overlap }; + +auto vehicle_status( const wrapped_vehicle &veh, const elevator_tiles &tiles ) -> overlap_status +{ + const auto &ps = veh.v->get_all_parts(); + const int all_vparts_count = ps.part_count(); + const int vparts_inside = std::count_if( ps.begin(), ps.end(), [&]( const vpart_reference & vp ) { + const tripoint p = veh.pos + vp.part().precalc[0]; + const auto eit = std::find( tiles.cbegin(), tiles.cend(), p ); + return eit != tiles.cend(); + } ); + + if( vparts_inside == all_vparts_count ) { + return overlap_status::inside; + } else if( vparts_inside == 0 ) { + return overlap_status::outside; + } else { + return overlap_status::overlap; + } +} + +struct elevator_vehicles { + bool blocking = false; + std::vector v; +}; + +auto get_vehicles_on_elevator( const elevator_tiles &tiles ) -> elevator_vehicles +{ + const VehicleList vehs = get_map().get_vehicles(); + std::vector ret; + + for( const wrapped_vehicle &veh : vehs ) { + const auto status = vehicle_status( veh, tiles ); + if( status == overlap_status::overlap ) { + return { true, { veh.v } }; + } + if( status == overlap_status::inside ) { + ret.push_back( veh.v ); + } + } + return { false, ret }; +} + +} // namespace + +namespace +{ + +// still not sure whether there's a utility function for this +// NOLINTNEXTLINE(bugprone-easily-swappable-parameters) +auto move_item( map &here, const tripoint &src, const tripoint &dest ) -> void +{ + map_stack items = here.i_at( src ); + for( auto it = items.begin(); it != items.end(); ) { + here.add_item_or_charges( dest, *it ); + it = here.i_rem( src, it ); + } +}; + +auto move_creatures_away_from( const elevator_tiles &dest ) -> void +{ + map &here = get_map(); + + const auto is_movable = [&]( const tripoint & candidate ) { + return !here.has_flag( TFLAG_ELEVATOR, candidate ) + && here.passable( candidate ) + && !g->critter_at( candidate ); + }; + + for( Creature &critter : g->all_creatures() ) { + const tripoint local_pos = here.getlocal( here.getglobal( critter.pos() ) ); + + const auto eit = std::find( dest.cbegin(), dest.cend(), local_pos ); + if( eit == dest.cend() ) { + continue; + } + + const auto xs = closest_points_first( *eit, 10 ); + const auto candidate = std::find_if( xs.begin(), xs.end(), is_movable ); + if( candidate == xs.end() ) { + continue; + } + critter.setpos( *candidate ); + } +} + +} //namespace + +/** + * If underground, move 2 levels up else move 2 levels down. Stable movement between levels 0 and -2. + */ +void iexamine::elevator( player &p, const tripoint &examp ) +{ + map &here = get_map(); + const tripoint_abs_ms old_abs_pos = here.getglobal( p.pos() ); + const tripoint_abs_omt this_omt = project_to( here.getglobal( examp ) ); + const tripoint sm_orig = here.getlocal( project_to( this_omt ) ); + + const auto elevator_here = get_elevator_here( p ); + const auto vehs = get_vehicles_on_elevator( elevator_here ); + if( vehs.blocking ) { + const auto &first_veh_name = vehs.v.front()->name; + popup( string_format( _( "The %s is blocking the elevator." ), first_veh_name ) ); + return; + } + + const int movez = choose_elevator_destz( examp, this_omt, sm_orig ); + if( movez < -OVERMAP_DEPTH ) { + return; + } + + const tripoint_abs_omt that_omt{ this_omt.xy(), movez }; + const int turns = get_rot_delta( this_omt, that_omt ); + + const auto elevator_dest = get_elevator_dest( elevator_here, sm_orig, turns, movez ); + + move_creatures_away_from( elevator_dest ); + + // move along every item in the elevator + for( decltype( elevator_here )::size_type i = 0; i < elevator_here.size(); i++ ) { + const tripoint &src = elevator_here[i]; + move_item( here, src, elevator_dest[i] ); + } + + // move along all creatures on the elevator + for( Creature &critter : g->all_creatures() ) { + const auto eit = std::find( elevator_here.cbegin(), elevator_here.cend(), critter.pos() ); + if( eit != elevator_here.cend() ) { + critter.setpos( elevator_dest[ std::distance( elevator_here.cbegin(), eit ) ] ); + } + } + + // move vehicles + for( vehicle *v : vehs.v ) { + const tripoint p = rotate_point_sm( { v->global_pos3().xy(), movez }, sm_orig, turns ); + here.displace_vehicle( *v, p - v->global_pos3() ); + v->turn( turns * 90_degrees ); + v->face = tileray( v->turn_dir ); + v->precalc_mounts( 0, v->turn_dir, v->pivot_anchor[0] ); + } + here.reset_vehicle_cache(); + + g->vertical_shift( movez ); + cata_event_dispatch::avatar_moves( *p.as_avatar(), here, old_abs_pos.raw() ); +} From 51a12e20369986bdf8f6f3c2e3d8ed5826e6cfc4 Mon Sep 17 00:00:00 2001 From: scarf Date: Sat, 16 Sep 2023 20:41:54 +0900 Subject: [PATCH 5/8] refactor: split into functions --- src/iexamine_elevator.cpp | 154 ++++++++++++++++++++------------------ 1 file changed, 82 insertions(+), 72 deletions(-) diff --git a/src/iexamine_elevator.cpp b/src/iexamine_elevator.cpp index d5d5c23b7231..42936d77cb02 100644 --- a/src/iexamine_elevator.cpp +++ b/src/iexamine_elevator.cpp @@ -11,17 +11,31 @@ #include "ui.h" #include "vpart_range.h" #include "point_rotate.h" - namespace { -using elevator_tiles = std::vector; -auto get_elevator_here( const Character &you ) -> elevator_tiles +// still not sure whether there's a utility function for this +// NOLINTNEXTLINE(bugprone-easily-swappable-parameters) +auto move_item( map &here, const tripoint &src, const tripoint &dest ) -> void +{ + map_stack items = here.i_at( src ); + for( auto it = items.begin(); it != items.end(); ) { + here.add_item_or_charges( dest, *it ); + it = here.i_rem( src, it ); + } +}; + +namespace elevator +{ + +using tiles = std::vector; + +auto here( const Character &you ) -> elevator::tiles { const auto &here = get_map(); const auto &points = closest_points_first( you.pos(), SEEX - 1 ); - elevator_tiles tiles; + elevator::tiles tiles; std::copy_if( points.begin(), points.end(), std::back_inserter( tiles ), [&here]( const tripoint & pos ) { return here.has_flag( TFLAG_ELEVATOR, pos ); @@ -30,12 +44,12 @@ auto get_elevator_here( const Character &you ) -> elevator_tiles return tiles; } -auto get_elevator_dest( const elevator_tiles &elevator_here, - const tripoint &sm_orig, - int turns, - int movez ) -> elevator_tiles +auto dest( const elevator::tiles &elevator_here, + const tripoint &sm_orig, + int turns, + int movez ) -> elevator::tiles { - elevator_tiles tiles; + elevator::tiles tiles; std::transform( elevator_here.begin(), elevator_here.end(), std::back_inserter( tiles ), [turns, &sm_orig, movez]( tripoint const & p ) { return rotate_point_sm( { p.xy(), movez }, sm_orig, turns ); @@ -44,40 +58,36 @@ auto get_elevator_dest( const elevator_tiles &elevator_here, return tiles; } -auto choose_elevator_destz( const tripoint &examp, const tripoint_abs_omt &this_omt, - const tripoint &sm_orig ) -> int +auto choose_floor( const tripoint &examp, const tripoint_abs_omt &this_omt, + const tripoint &sm_orig ) -> int { const auto this_floor = _( " (this floor)" ); map &here = get_map(); uilist choice; - choice.title = _( "Select destination floor" ); + choice.title = _( "Please select destination floor" ); for( int z = OVERMAP_HEIGHT; z >= -OVERMAP_DEPTH; z-- ) { const tripoint_abs_omt that_omt{ this_omt.xy(), z }; const int delta = get_rot_delta( this_omt, that_omt ); const tripoint zp = rotate_point_sm( { examp.xy(), z }, sm_orig, delta ); - if( here.ter( zp )->examine == &iexamine::elevator ) { - const std::string omt_name = overmap_buffer.ter_existing( that_omt )->get_name(); - const auto floor_name = z == examp.z ? this_floor : ""; - const std::string name = string_format( "%3iF %s%s", z, omt_name, floor_name ); - - choice.addentry( z, z != examp.z, MENU_AUTOASSIGN, name ); + if( here.ter( zp )->examine != &iexamine::elevator ) { + continue; } + const std::string omt_name = overmap_buffer.ter_existing( that_omt )->get_name(); + const auto floor_name = z == examp.z ? this_floor : ""; + const std::string name = string_format( "%3iF %s%s", z, omt_name, floor_name ); + + choice.addentry( z, z != examp.z, MENU_AUTOASSIGN, name ); } choice.query(); return choice.ret; } -} // namespace - -namespace -{ - enum class overlap_status { outside, inside, overlap }; -auto vehicle_status( const wrapped_vehicle &veh, const elevator_tiles &tiles ) -> overlap_status +auto vehicle_status( const wrapped_vehicle &veh, const elevator::tiles &tiles ) -> overlap_status { const auto &ps = veh.v->get_all_parts(); const int all_vparts_count = ps.part_count(); @@ -101,7 +111,7 @@ struct elevator_vehicles { std::vector v; }; -auto get_vehicles_on_elevator( const elevator_tiles &tiles ) -> elevator_vehicles +auto vehicles_on( const elevator::tiles &tiles ) -> elevator_vehicles { const VehicleList vehs = get_map().get_vehicles(); std::vector ret; @@ -118,23 +128,7 @@ auto get_vehicles_on_elevator( const elevator_tiles &tiles ) -> elevator_vehicle return { false, ret }; } -} // namespace - -namespace -{ - -// still not sure whether there's a utility function for this -// NOLINTNEXTLINE(bugprone-easily-swappable-parameters) -auto move_item( map &here, const tripoint &src, const tripoint &dest ) -> void -{ - map_stack items = here.i_at( src ); - for( auto it = items.begin(); it != items.end(); ) { - here.add_item_or_charges( dest, *it ); - it = here.i_rem( src, it ); - } -}; - -auto move_creatures_away_from( const elevator_tiles &dest ) -> void +auto move_creatures_away( const elevator::tiles &dest ) -> void { map &here = get_map(); @@ -161,7 +155,44 @@ auto move_creatures_away_from( const elevator_tiles &dest ) -> void } } -} //namespace +auto move_items( const elevator::tiles from, const elevator::tiles dest ) -> void +{ + map &here = get_map(); + + for( decltype( from )::size_type i = 0; i < from.size(); i++ ) { + const tripoint &src = from[i]; + move_item( here, src, dest[i] ); + } +} + +auto move_creatures( const elevator::tiles from, const elevator::tiles dest ) -> void +{ + for( Creature &critter : g->all_creatures() ) { + const auto eit = std::find( from.cbegin(), from.cend(), critter.pos() ); + if( eit != from.cend() ) { + critter.setpos( dest[ std::distance( from.cbegin(), eit ) ] ); + } + } +} + +auto move_vehicles( const elevator_vehicles &vehs, const tripoint &sm_orig, int movez, + int turns ) -> void +{ + map &here = get_map(); + + for( vehicle *v : vehs.v ) { + const tripoint p = rotate_point_sm( { v->global_pos3().xy(), movez }, sm_orig, turns ); + here.displace_vehicle( *v, p - v->global_pos3() ); + v->turn( turns * 90_degrees ); + v->face = tileray( v->turn_dir ); + v->precalc_mounts( 0, v->turn_dir, v->pivot_anchor[0] ); + } + here.reset_vehicle_cache(); +} + +} //namespace elevator + +} // namespace /** * If underground, move 2 levels up else move 2 levels down. Stable movement between levels 0 and -2. @@ -173,15 +204,15 @@ void iexamine::elevator( player &p, const tripoint &examp ) const tripoint_abs_omt this_omt = project_to( here.getglobal( examp ) ); const tripoint sm_orig = here.getlocal( project_to( this_omt ) ); - const auto elevator_here = get_elevator_here( p ); - const auto vehs = get_vehicles_on_elevator( elevator_here ); + const auto elevator_here = elevator::here( p ); + const auto vehs = elevator::vehicles_on( elevator_here ); if( vehs.blocking ) { const auto &first_veh_name = vehs.v.front()->name; popup( string_format( _( "The %s is blocking the elevator." ), first_veh_name ) ); return; } - const int movez = choose_elevator_destz( examp, this_omt, sm_orig ); + const int movez = elevator::choose_floor( examp, this_omt, sm_orig ); if( movez < -OVERMAP_DEPTH ) { return; } @@ -189,33 +220,12 @@ void iexamine::elevator( player &p, const tripoint &examp ) const tripoint_abs_omt that_omt{ this_omt.xy(), movez }; const int turns = get_rot_delta( this_omt, that_omt ); - const auto elevator_dest = get_elevator_dest( elevator_here, sm_orig, turns, movez ); - - move_creatures_away_from( elevator_dest ); - - // move along every item in the elevator - for( decltype( elevator_here )::size_type i = 0; i < elevator_here.size(); i++ ) { - const tripoint &src = elevator_here[i]; - move_item( here, src, elevator_dest[i] ); - } - - // move along all creatures on the elevator - for( Creature &critter : g->all_creatures() ) { - const auto eit = std::find( elevator_here.cbegin(), elevator_here.cend(), critter.pos() ); - if( eit != elevator_here.cend() ) { - critter.setpos( elevator_dest[ std::distance( elevator_here.cbegin(), eit ) ] ); - } - } + const auto elevator_dest = elevator::dest( elevator_here, sm_orig, turns, movez ); - // move vehicles - for( vehicle *v : vehs.v ) { - const tripoint p = rotate_point_sm( { v->global_pos3().xy(), movez }, sm_orig, turns ); - here.displace_vehicle( *v, p - v->global_pos3() ); - v->turn( turns * 90_degrees ); - v->face = tileray( v->turn_dir ); - v->precalc_mounts( 0, v->turn_dir, v->pivot_anchor[0] ); - } - here.reset_vehicle_cache(); + elevator::move_creatures_away( elevator_dest ); + elevator::move_items( elevator_here, elevator_dest ); + elevator::move_creatures( elevator_here, elevator_dest ); + elevator::move_vehicles( vehs, sm_orig, movez, turns ); g->vertical_shift( movez ); cata_event_dispatch::avatar_moves( *p.as_avatar(), here, old_abs_pos.raw() ); From 60773630e7a9eda52d7a7d7923e1ea5e8d90ba52 Mon Sep 17 00:00:00 2001 From: scarf Date: Sat, 16 Sep 2023 21:03:42 +0900 Subject: [PATCH 6/8] fix: negative retval `-1`confuses uilist prevent exciting magic numbers from happening Co-authored-by: andrei <68240139+andrei8l@users.noreply.github.com> --- src/iexamine_elevator.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/iexamine_elevator.cpp b/src/iexamine_elevator.cpp index 42936d77cb02..ed1b209d4fee 100644 --- a/src/iexamine_elevator.cpp +++ b/src/iexamine_elevator.cpp @@ -61,6 +61,7 @@ auto dest( const elevator::tiles &elevator_here, auto choose_floor( const tripoint &examp, const tripoint_abs_omt &this_omt, const tripoint &sm_orig ) -> int { + constexpr int retval_offset = 10000; // workaround for uilist retval autoassign when retval == -1 const auto this_floor = _( " (this floor)" ); map &here = get_map(); @@ -79,10 +80,10 @@ auto choose_floor( const tripoint &examp, const tripoint_abs_omt &this_omt, const auto floor_name = z == examp.z ? this_floor : ""; const std::string name = string_format( "%3iF %s%s", z, omt_name, floor_name ); - choice.addentry( z, z != examp.z, MENU_AUTOASSIGN, name ); + choice.addentry( z + retval_offset, z != examp.z, MENU_AUTOASSIGN, name ); } choice.query(); - return choice.ret; + return choice.ret - retval_offset; } enum class overlap_status { outside, inside, overlap }; From 4b5bff5963a6d7cfe662f023fd566c971b929797 Mon Sep 17 00:00:00 2001 From: scarf Date: Sat, 16 Sep 2023 21:21:14 +0900 Subject: [PATCH 7/8] fix: check vehicles in destination too prevents exciting amalgamations from happening --- src/iexamine_elevator.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/iexamine_elevator.cpp b/src/iexamine_elevator.cpp index ed1b209d4fee..8996d3257313 100644 --- a/src/iexamine_elevator.cpp +++ b/src/iexamine_elevator.cpp @@ -129,6 +129,12 @@ auto vehicles_on( const elevator::tiles &tiles ) -> elevator_vehicles return { false, ret }; } +auto warn_blocking( const elevator_vehicles &vehs, std::string_view location ) -> void +{ + const auto &first_veh_name = vehs.v.front()->name; + popup( string_format( _( "%1$s %2$s is blocking the elevator." ), first_veh_name, location ) ); +} + auto move_creatures_away( const elevator::tiles &dest ) -> void { map &here = get_map(); @@ -208,9 +214,7 @@ void iexamine::elevator( player &p, const tripoint &examp ) const auto elevator_here = elevator::here( p ); const auto vehs = elevator::vehicles_on( elevator_here ); if( vehs.blocking ) { - const auto &first_veh_name = vehs.v.front()->name; - popup( string_format( _( "The %s is blocking the elevator." ), first_veh_name ) ); - return; + return warn_blocking( vehs, _( "here" ) ); } const int movez = elevator::choose_floor( examp, this_omt, sm_orig ); @@ -222,6 +226,10 @@ void iexamine::elevator( player &p, const tripoint &examp ) const int turns = get_rot_delta( this_omt, that_omt ); const auto elevator_dest = elevator::dest( elevator_here, sm_orig, turns, movez ); + const auto vehicles_dest = elevator::vehicles_on( elevator_dest ); + if( !vehicles_dest.v.empty() ) { + return warn_blocking( vehicles_dest, _( "at the destination floor" ) ); + } elevator::move_creatures_away( elevator_dest ); elevator::move_items( elevator_here, elevator_dest ); From f1780cacbab33a971fd195b0b9521d16da612cbe Mon Sep 17 00:00:00 2001 From: scarf Date: Sun, 17 Sep 2023 08:37:08 +0900 Subject: [PATCH 8/8] fix: include headers make MSYS2 happy --- src/point_rotate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/point_rotate.cpp b/src/point_rotate.cpp index 5f31f8f17090..590350aa6fba 100644 --- a/src/point_rotate.cpp +++ b/src/point_rotate.cpp @@ -1,3 +1,4 @@ +#include "point_rotate.h" #include "overmapbuffer.h" #include "omdata.h" #include "point.h"