Skip to content

Commit

Permalink
Prevents moving through vehicle holes
Browse files Browse the repository at this point in the history
  • Loading branch information
joveeater committed Jun 28, 2022
1 parent 81039bc commit 880fcd9
Show file tree
Hide file tree
Showing 32 changed files with 1,217 additions and 183 deletions.
20 changes: 17 additions & 3 deletions src/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,11 @@ action_id handle_action_menu()
// display that action at the top of the list.
for( const tripoint &pos : g->m.points_in_radius( g->u.pos(), 1 ) ) {
if( pos != g->u.pos() ) {
// Check for actions that work on nearby tiles
// Check for actions that work on nearby tiles, skipping tiles blocked by vehicles
if( g->m.obstructed_by_vehicle_rotation( g->u.pos(), pos ) ) {
continue;
}

if( can_interact_at( ACTION_OPEN, pos ) ) {
action_weightings[ACTION_OPEN] = 200;
}
Expand Down Expand Up @@ -1006,7 +1010,17 @@ cata::optional<tripoint> choose_direction( const std::string &message, const boo
cata::optional<tripoint> choose_adjacent( const std::string &message, const bool allow_vertical )
{
const cata::optional<tripoint> dir = choose_direction( message, allow_vertical );
return dir ? *dir + g->u.pos() : dir;

if( !dir ) {
return cata::nullopt;
}

if( g->m.obstructed_by_vehicle_rotation( g->u.pos(), *dir + g->u.pos() ) ) {
add_msg( _( "You can't reach through that vehicle's wall." ) );
return cata::nullopt;
}

return *dir + g->u.pos();
}

cata::optional<tripoint> choose_adjacent_highlight( const std::string &message,
Expand All @@ -1025,7 +1039,7 @@ cata::optional<tripoint> choose_adjacent_highlight( const std::string &message,
std::vector<tripoint> valid;
if( allowed ) {
for( const tripoint &pos : g->m.points_in_radius( g->u.pos(), 1 ) ) {
if( allowed( pos ) ) {
if( !g->m.obstructed_by_vehicle_rotation( g->u.pos(), pos ) && allowed( pos ) ) {
valid.emplace_back( pos );
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/avatar_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,11 @@ bool avatar_action::move( avatar &you, map &m, const tripoint &d )
return false;
}

if( m.obstructed_by_vehicle_rotation( you.pos(), dest_loc ) ) {
add_msg( _( "You can't walk through that vehicle's wall." ) );
return false;
}

if( monster *const mon_ptr = g->critter_at<monster>( dest_loc, true ) ) {
monster &critter = *mon_ptr;
if( critter.friendly == 0 &&
Expand Down
20 changes: 20 additions & 0 deletions src/ballistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,26 @@ dealt_projectile_attack projectile_attack( const projectile &proj_arg, const tri
} else if( in_veh != nullptr && veh_pointer_or_null( g->m.veh_at( tp ) ) == in_veh ) {
// Don't do anything, especially don't call map::shoot as this would damage the vehicle
} else {

if( g->m.obstructed_by_vehicle_rotation( prev_point, tp ) ) {
//We're firing through an impassible gap in a rotated vehicle, randomly hit one of the two walls
tripoint rand = tp;
if( one_in( 2 ) ) {
rand.x = prev_point.x;
} else {
rand.y = prev_point.y;
}
if( in_veh == nullptr || veh_pointer_or_null( g->m.veh_at( rand ) ) != in_veh ) {
g->m.shoot( rand, proj, false );
if( proj.impact.total_damage() <= 0 ) {
//If the projectile stops here move it back a square so it doesn't end up inside the vehicle
traj_len = i - 1;
tp = prev_point;
break;
}
}
}

g->m.shoot( tp, proj, !no_item_damage && tp == target );
has_momentum = proj.impact.total_damage() > 0;
}
Expand Down
5 changes: 4 additions & 1 deletion src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,12 @@ bool Creature::sees( const Creature &critter ) const

const Character *ch = critter.as_character();
const int wanted_range = rl_dist( pos(), critter.pos() );
// Can always see adjacent monsters on the same level.
// Can always see adjacent monsters on the same level, unless they're through a vehicle wall.
// We also bypass lighting for vertically adjacent monsters, but still check for floors.
if( wanted_range <= 1 && ( posz() == critter.posz() || g->m.sees( pos(), critter.pos(), 1 ) ) ) {
if( g->m.obscured_by_vehicle_rotation( pos(), critter.pos() ) ) {
return false;
}
return visible( ch );
} else if( ( wanted_range > 1 && critter.digging() ) ||
( critter.has_flag( MF_NIGHT_INVISIBILITY ) && g->m.light_at( critter.pos() ) <= lit_level::LOW ) ||
Expand Down
17 changes: 13 additions & 4 deletions src/explosion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ static std::map<const Creature *, int> do_blast( const tripoint &p, const float
// Iterate over all neighbors. Bash all of them, propagate to some
for( size_t i = 0; i < max_index; i++ ) {
tripoint dest( pt + tripoint( x_offset[i], y_offset[i], z_offset[i] ) );
if( closed.count( dest ) != 0 || !g->m.inbounds( dest ) ) {
if( closed.count( dest ) != 0 || !g->m.inbounds( dest ) ||
g->m.obstructed_by_vehicle_rotation( pt, dest ) ) {
continue;
}

Expand Down Expand Up @@ -438,11 +439,16 @@ static std::map<const Creature *, int> do_blast_new( const tripoint &blast_cente
for( const dist_point_pair &pair : blast_map ) {
float distance;
tripoint position;
tripoint last_position = position;
std::tie( distance, position ) = pair;

const std::vector<tripoint> line_of_movement = line_to( blast_center, position );
const bool has_obstacles = std::any_of( line_of_movement.begin(),
line_of_movement.end(), [position]( tripoint ray_position ) {
line_of_movement.end(), [position, &last_position]( tripoint ray_position ) {
if( get_map().obstructed_by_vehicle_rotation( last_position, ray_position ) ) {
return true;
}
last_position = ray_position;
return ray_position != position && get_map().impassable( ray_position );
} );

Expand Down Expand Up @@ -611,13 +617,15 @@ static std::map<const Creature *, int> shrapnel( const tripoint &src, const proj

float obstacle_cache[MAPSIZE_X][MAPSIZE_Y] = {};
float visited_cache[MAPSIZE_X][MAPSIZE_Y] = {};
diagonal_blocks blocked_cache[MAPSIZE_X][MAPSIZE_Y] = {};

// TODO: Calculate range based on max effective range for projectiles.
// Basically bisect between 0 and map diameter using shrapnel_calc().
// Need to update shadowcasting to support limiting range without adjusting initial distance.
const tripoint_range<tripoint> area = g->m.points_on_zlevel( src.z );

g->m.build_obstacle_cache( area.min(), area.max() + tripoint_south_east, obstacle_cache );
g->m.build_obstacle_cache( area.min(), area.max() + tripoint_south_east, obstacle_cache,
blocked_cache );

// Shadowcasting normally ignores the origin square,
// so apply it manually to catch monsters standing on the explosive.
Expand All @@ -629,7 +637,8 @@ static std::map<const Creature *, int> shrapnel( const tripoint &src, const proj
const int offset_distance = 60 - 1 - fragment.range;
castLightAll<float, float, shrapnel_calc, shrapnel_check,
update_fragment_cloud, accumulate_fragment_cloud>
( visited_cache, obstacle_cache, src.xy(), offset_distance, fragment.range + 1.0f );
( visited_cache, obstacle_cache, blocked_cache, src.xy(),
offset_distance, fragment.range + 1.0f );

// Now visited_caches are populated with density and velocity of fragments.
for( const tripoint &target : area ) {
Expand Down
Loading

0 comments on commit 880fcd9

Please sign in to comment.