-
Notifications
You must be signed in to change notification settings - Fork 277
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: crude working vehicle elevator
(with debug warnings)
- Loading branch information
Showing
4 changed files
with
185 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
#include "game.h" | ||
#include "iexamine.h" | ||
#include "mapdata.h" | ||
#include "output.h" | ||
#include "player.h" | ||
#include "coordinates.h" | ||
#include "map.h" | ||
#include "point.h" | ||
#include "vpart_range.h" | ||
|
||
namespace | ||
{ | ||
|
||
using elevator_tiles = std::vector<tripoint>; | ||
auto get_elevator_tiles( 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; | ||
} | ||
|
||
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<vehicle *> v; | ||
}; | ||
|
||
auto get_vehicles_on_elevator( const elevator_tiles &tiles ) -> elevator_vehicles | ||
{ | ||
const VehicleList vehs = get_map().get_vehicles(); | ||
std::vector<vehicle *> 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 }; | ||
} | ||
|
||
// auto choose_elevator_destination | ||
|
||
} // 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 auto elevator_here = get_elevator_tiles( p ); | ||
const auto vehs = get_vehicles_on_elevator( elevator_here ); | ||
if( vehs.blocking ) { | ||
popup( string_format( _( "The %s is blocking the elevator." ), vehs.v.front()->name ) ); | ||
return; | ||
} | ||
|
||
if( !query_yn( _( "Use the %s?" ), here.tername( examp ) ) ) { | ||
return; | ||
} | ||
|
||
// TODO: port z level selection in | ||
// https://github.com/CleverRaven/Cataclysm-DDA/pull/58840 | ||
const auto movez = tripoint( point_zero, examp.z < 0 ? 2 : -2 ); | ||
|
||
tripoint original_floor_omt = ms_to_omt_copy( here.getabs( examp ) ); | ||
tripoint new_floor_omt = original_floor_omt + 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( TFLAG_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( TFLAG_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( TFLAG_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( TFLAG_ELEVATOR, pos ) ) { | ||
map_stack items = here.i_at( pos ); | ||
tripoint dest = first_elevator_tile( pos + movez ); | ||
move_item( items, pos, dest ); | ||
} | ||
} | ||
|
||
// move the player | ||
g->vertical_move( movez.z, false ); | ||
|
||
// 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( TFLAG_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( TFLAG_ELEVATOR, candidate ) && candidate != p.pos() && | ||
!g->critter_at( candidate ) ) { | ||
critter.setpos( candidate ); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
for( vehicle *v : vehs.v ) { | ||
here.displace_vehicle( *v, movez ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters