Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 73 additions & 8 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1452,19 +1452,63 @@ bool map::displace_vehicle( vehicle &veh, const tripoint &dp, const bool adjust_
const tripoint_bub_ms src = veh.pos_bub();
// handle vehicle ramps
int ramp_offset = 0;
if( adjust_pos ) {
if( has_flag( ter_furn_flag::TFLAG_RAMP_UP, src + dp ) ) {
ramp_offset += 1;
veh.is_on_ramp = true;
} else if( has_flag( ter_furn_flag::TFLAG_RAMP_DOWN, src + dp ) ) {
ramp_offset -= 1;
veh.is_on_ramp = true;
bool stacked_decks = false;
for( int i = 0; i < veh.num_parts(); i++ ) {
if( !veh.part( i ).removed && veh.part( i ).mount_z > 0 ) {
stacked_decks = true;
break;
}
}
if( adjust_pos && !veh.is_flying_in_air() ) {
if( stacked_decks ) {
const tripoint base = veh.global_pos3();
int lowest = 1;
bool any_col = false;
for( int i = 0; i < veh.num_parts(); i++ ) {
const vehicle_part &vp = veh.part( i );
if( vp.removed || vp.mount_z != 0 ) {
continue;
}
const tripoint cur = base + vp.precalc[0];
const tripoint rc( cur.x + dp.x, cur.y + dp.y, cur.z );
int col = cur.z - base.z;
if( has_flag( ter_furn_flag::TFLAG_RAMP_UP, rc ) ) {
col += 1;
} else if( has_flag( ter_furn_flag::TFLAG_RAMP_DOWN, rc ) ) {
col -= 1;
}
col = std::min( 1, std::max( -1, col ) );
lowest = std::min( lowest, col );
any_col = true;
}
ramp_offset = any_col ? lowest : 0;
if( ramp_offset != 0 ) {
veh.is_on_ramp = true;
}
} else {
bool ramp_up = has_flag( ter_furn_flag::TFLAG_RAMP_UP, src + dp );
bool ramp_down = has_flag( ter_furn_flag::TFLAG_RAMP_DOWN, src + dp );
if( ramp_up ) {
ramp_offset += 1;
veh.is_on_ramp = true;
} else if( ramp_down ) {
ramp_offset -= 1;
veh.is_on_ramp = true;
}
}
}

const tripoint_bub_ms dst =
src + ( adjust_pos ? ( dp + tripoint( 0, 0, ramp_offset ) ) : tripoint_zero );

if( src.z() != dst.z() ) {
DebugLog( D_INFO, D_MAIN ) << "[VEHDBG] zchange " << veh.name
<< " src=" << src.x() << "," << src.y() << "," << src.z()
<< " dst=" << dst.x() << "," << dst.y() << "," << dst.z()
<< " dp=" << dp.x << "," << dp.y << "," << dp.z
<< " ramp=" << ramp_offset;
}

if( !inbounds( src ) ) {
add_msg_debug( debugmode::DF_MAP,
"map::displace_vehicle: coordinates out of bounds %d,%d,%d->%d,%d,%d",
Expand Down Expand Up @@ -1560,7 +1604,20 @@ bool map::displace_vehicle( vehicle &veh, const tripoint &dp, const bool adjust_
// ramps make everything super tricky
int psg_offset_z = -ramp_offset;
tripoint next_pos = veh_part.precalc[1];
if( has_flag( ter_furn_flag::TFLAG_RAMP_UP, src + dp + next_pos ) ) {
if( stacked_decks ) {
int col_ramp = next_pos.z - veh_part.mount_z;
if( !veh.is_flying_in_air() ) {
const tripoint rc( dst.x() + next_pos.x, dst.y() + next_pos.y,
src.z() + next_pos.z - veh_part.mount_z );
if( has_flag( ter_furn_flag::TFLAG_RAMP_UP, rc ) ) {
col_ramp += 1;
} else if( has_flag( ter_furn_flag::TFLAG_RAMP_DOWN, rc ) ) {
col_ramp -= 1;
}
}
col_ramp = std::min( 1, std::max( -1, col_ramp ) );
psg_offset_z = veh_part.mount_z + col_ramp - ramp_offset - next_pos.z;
} else if( has_flag( ter_furn_flag::TFLAG_RAMP_UP, src + dp + next_pos ) ) {
psg_offset_z += 1;
} else if( has_flag( ter_furn_flag::TFLAG_RAMP_DOWN, src + dp + next_pos ) ) {
psg_offset_z -= 1;
Expand All @@ -1570,13 +1627,21 @@ bool map::displace_vehicle( vehicle &veh, const tripoint &dp, const bool adjust_
tripoint_bub_ms psgp( dst + next_pos + tripoint( 0, 0, psg_offset_z ) );
// someone is in the way so try again
if( creatures.creature_at( psgp ) ) {
DebugLog( D_INFO, D_MAIN ) << "[VEHDBG] rider blocked part=" << prt
<< " psgp=" << psgp.x() << "," << psgp.y() << "," << psgp.z();
complete = false;
continue;
}
if( psg->is_avatar() ) {
// If passenger is you, we need to update the map
need_update = true;
z_change = psgp.z() - part_pos.z;
DebugLog( D_INFO, D_MAIN ) << "[VEHDBG] avatar part=" << prt
<< " from=" << part_pos.x << "," << part_pos.y << "," << part_pos.z
<< " to=" << psgp.x() << "," << psgp.y() << "," << psgp.z()
<< " zchg=" << z_change
<< " ramp=" << ramp_offset
<< " dst_z=" << dst.z();
}

psg->setpos( psgp.raw() );
Expand Down
31 changes: 26 additions & 5 deletions src/vehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8192,6 +8192,10 @@ std::set<int> vehicle::advance_precalc_mounts( const point &new_pos, const tripo
{
map &here = get_map();
std::set<int> smzs;
const bool stacked_decks = std::any_of( parts.begin(), parts.end(),
[]( const vehicle_part &prt ) {
return !prt.removed && prt.mount_z > 0;
} );
// when a vehicle part enters the low end of a down ramp, or the high end of an up ramp,
// it immediately translates down or up a z-level, respectively, ending up on the low
// end of an up ramp or high end of a down ramp, respectively. The two ends are set
Expand Down Expand Up @@ -8231,12 +8235,29 @@ std::set<int> vehicle::advance_precalc_mounts( const point &new_pos, const tripo
} else if( !adjust_pos && parts_to_move.find( index ) != parts_to_move.end() ) {
prt.precalc[0].z += dp.z;
}
if( here.has_flag( ter_furn_flag::TFLAG_RAMP_UP, src + dp + prt.precalc[0] ) ) {
prt.precalc[0].z += 1;
} else if( here.has_flag( ter_furn_flag::TFLAG_RAMP_DOWN, src + dp + prt.precalc[0] ) ) {
prt.precalc[0].z -= 1;
if( stacked_decks ) {
int col_ramp = prt.precalc[1].z - prt.mount_z;
if( !is_flying_in_air() ) {
const tripoint cur = src + prt.precalc[0];
const tripoint rc( cur.x + dp.x, cur.y + dp.y, cur.z - prt.mount_z );
if( here.has_flag( ter_furn_flag::TFLAG_RAMP_UP, rc ) ) {
col_ramp += 1;
} else if( here.has_flag( ter_furn_flag::TFLAG_RAMP_DOWN, rc ) ) {
col_ramp -= 1;
}
}
col_ramp = std::min( 1, std::max( -1, col_ramp ) );
prt.precalc[0].z = prt.mount_z + col_ramp - ramp_offset;
} else {
if( !is_flying_in_air() ) {
if( here.has_flag( ter_furn_flag::TFLAG_RAMP_UP, src + dp + prt.precalc[0] ) ) {
prt.precalc[0].z += 1;
} else if( here.has_flag( ter_furn_flag::TFLAG_RAMP_DOWN, src + dp + prt.precalc[0] ) ) {
prt.precalc[0].z -= 1;
}
}
prt.precalc[0].z -= ramp_offset;
}
prt.precalc[0].z -= ramp_offset;
prt.precalc[1].z = prt.precalc[0].z;
smzs.insert( prt.precalc[0].z );
}
Expand Down
160 changes: 147 additions & 13 deletions src/vehicle_move.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,49 @@ bool vehicle::collision( std::vector<veh_collision> &colls,
// and turning (precalc[1])
const tripoint dsp = global_pos3() + dp + parts[p].precalc[1];
veh_collision coll = part_collision( p, dsp, just_detect, bash_floor );
if( coll.type != veh_coll_nothing ) {
static int dbg_coll = 0;
static bool dbg_scanned = false;
const tripoint vp = global_pos3();
if( velocity != 0 || ++dbg_coll % 20 == 1 ) {
DebugLog( D_INFO, D_MAIN ) << "[VEHDBG] collide " << name
<< " pos=" << vp.x << "," << vp.y << "," << vp.z
<< " part=" << p
<< " mount=" << parts[p].mount.x << "," << parts[p].mount.y << "," << parts[p].mount_z
<< " precalc=" << parts[p].precalc[1].x << "," << parts[p].precalc[1].y << "," << parts[p].precalc[1].z
<< " dp=" << dp.x << "," << dp.y << "," << dp.z
<< " dsp=" << dsp.x << "," << dsp.y << "," << dsp.z
<< " ter=" << here.ter( dsp ).id().str()
<< " ctype=" << static_cast<int>( coll.type )
<< " tname=" << coll.target_name
<< " origter=" << here.ter( vp ).id().str()
<< " mc=" << here.move_cost_ter_furn( dsp )
<< " furn=" << here.furn( dsp ).id().str()
<< " bash=" << here.is_bashable_ter_furn( dsp, false )
<< " bashfloor=" << bash_floor
<< " detect=" << just_detect
<< " vel=" << velocity;
}
if( !dbg_scanned ) {
dbg_scanned = true;
for( int dz = 0; dz <= 1; dz++ ) {
for( int dy = -3; dy <= 3; dy++ ) {
std::string row;
for( int dx = -3; dx <= 3; dx++ ) {
const tripoint q( vp.x + dx, vp.y + dy, vp.z + dz );
if( here.inbounds( q ) ) {
row += here.ter( q ).id().str();
} else {
row += "oob";
}
row += " ";
}
DebugLog( D_INFO, D_MAIN ) << "[VEHDBG] scan z=" << ( vp.z + dz )
<< " y=" << ( vp.y + dy ) << " | " << row;
}
}
}
}
if( coll.type == veh_coll_nothing && info.rotor_diameter() > 0 ) {
size_t radius = static_cast<size_t>( std::round( info.rotor_diameter() / 2.0f ) );
for( const tripoint &rotor_point : here.points_in_radius( dsp, radius ) ) {
Expand Down Expand Up @@ -1361,12 +1404,23 @@ void vehicle::selfdrive( const point &p )

bool vehicle::check_is_heli_landed()
{
// @TODO - when there are chasms that extend below z-level 0 - perhaps the heli
// will be able to descend into them but for now, assume z-level-0 == the ground.
if( global_pos3().z == 0 ||
!get_map().has_flag_ter_or_furn( ter_furn_flag::TFLAG_NO_FLOOR, global_pos3() ) ) {
is_flying = false;
return true;
map &here = get_map();
std::map<point, int> column_bottom;
for( const tripoint &pt : get_points( true ) ) {
auto it = column_bottom.find( pt.xy() );
if( it == column_bottom.end() ) {
column_bottom.emplace( pt.xy(), pt.z );
} else if( pt.z < it->second ) {
it->second = pt.z;
}
}
for( const auto &col : column_bottom ) {
const tripoint bottom( col.first, col.second );
if( bottom.z <= -OVERMAP_DEPTH ||
!here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_NO_FLOOR, bottom ) ) {
is_flying = false;
return true;
}
}
return false;
}
Expand Down Expand Up @@ -1840,6 +1894,57 @@ vehicle *vehicle::act_on_map()
{
const tripoint pt = global_pos3();
map &here = get_map();
{
static int dbg_state = 0;
if( ++dbg_state % 10 == 0 ) {
std::map<int, int> decks;
for( const vehicle_part &vp : parts ) {
if( !vp.removed ) {
decks[vp.mount_z]++;
}
}
const std::set<tripoint> &dbg_pts = get_points( true );
int minx = 0, maxx = 0, miny = 0, maxy = 0;
if( !dbg_pts.empty() ) {
minx = maxx = dbg_pts.begin()->x;
miny = maxy = dbg_pts.begin()->y;
for( const tripoint &gp : dbg_pts ) {
minx = std::min( minx, gp.x );
maxx = std::max( maxx, gp.x );
miny = std::min( miny, gp.y );
maxy = std::max( maxy, gp.y );
}
}
DebugLog( D_INFO, D_MAIN ) << "[VEHDBG] state " << name
<< " pos=" << pt.x << "," << pt.y << "," << pt.z
<< " bbox=" << minx << "," << miny << "~" << maxx << "," << maxy
<< " falling=" << is_falling
<< " flying=" << is_flying
<< " water=" << in_water
<< " float=" << is_floating
<< " decks=" << decks.size();
std::map<int, int> real_z;
for( const vehicle_part &vp : parts ) {
if( !vp.removed ) {
real_z[global_part_pos3( vp ).z]++;
}
}
for( const auto &d : real_z ) {
DebugLog( D_INFO, D_MAIN ) << "[VEHDBG] actual_z=" << d.first
<< " parts=" << d.second;
}
for( int mz = 0; mz < 3; mz++ ) {
for( const vehicle_part &vp : parts ) {
if( !vp.removed && vp.mount_z == mz ) {
DebugLog( D_INFO, D_MAIN ) << "[VEHDBG] sample mount=" << mz
<< " precalc=" << vp.precalc[1].z
<< " abs=" << global_part_pos3( vp ).z;
break;
}
}
}
}
}
if( !here.inbounds( pt ) ) {
dbg( D_INFO ) << "stopping out-of-map vehicle. (x,y,z)=(" << pt.x << "," << pt.y << "," << pt.z <<
")";
Expand Down Expand Up @@ -2071,6 +2176,10 @@ bool vehicle::level_vehicle()
if( is_flying && is_rotorcraft() ) {
return true;
}
const bool stacked_decks = std::any_of( parts.begin(), parts.end(),
[]( const vehicle_part &prt ) {
return !prt.removed && prt.mount_z > 0;
} );
is_on_ramp = false;
// make sure that all parts are either supported across levels or on the same level
std::map<int, bool> no_support;
Expand All @@ -2079,12 +2188,14 @@ bool vehicle::level_vehicle()
continue;
}
const tripoint part_pos = global_part_pos3( prt );
if( no_support.find( part_pos.z ) == no_support.end() ) {
no_support[part_pos.z] = part_pos.z > -OVERMAP_DEPTH;
}
if( no_support[part_pos.z] ) {
no_support[part_pos.z] = here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_NO_FLOOR, part_pos ) &&
!here.supports_above( part_pos + tripoint_below );
if( !stacked_decks ) {
if( no_support.find( part_pos.z ) == no_support.end() ) {
no_support[part_pos.z] = part_pos.z > -OVERMAP_DEPTH;
}
if( no_support[part_pos.z] ) {
no_support[part_pos.z] = here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_NO_FLOOR, part_pos ) &&
!here.supports_above( part_pos + tripoint_below );
}
}
if( !is_on_ramp &&
( here.has_flag( ter_furn_flag::TFLAG_RAMP_UP, tripoint( part_pos.xy(), part_pos.z - 1 ) ) ||
Expand Down Expand Up @@ -2187,8 +2298,31 @@ void vehicle::check_falling_or_floating()
deep_water_tiles += here.has_flag( ter_furn_flag::TFLAG_DEEP_WATER, position ) ? 1 : 0;
water_tiles += here.has_flag( ter_furn_flag::TFLAG_SWIMMABLE, position ) ? 1 : 0;
}
}
const bool stacked_decks = std::any_of( parts.begin(), parts.end(),
[]( const vehicle_part &prt ) {
return !prt.removed && prt.mount_z > 0;
} );
std::set<tripoint> support_check;
if( stacked_decks ) {
std::map<point, int> column_bottom;
for( const tripoint &pt : pts ) {
auto it = column_bottom.find( pt.xy() );
if( it == column_bottom.end() ) {
column_bottom.emplace( pt.xy(), pt.z );
} else if( pt.z < it->second ) {
it->second = pt.z;
}
}
for( const auto &col : column_bottom ) {
support_check.insert( tripoint( col.first, col.second ) );
}
} else {
support_check = pts;
}
for( const tripoint &position : support_check ) {
if( !is_falling ) {
continue;
break;
}
is_falling = !has_support( position, true );
}
Expand Down
Loading