Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn on 3D FOV by default and combine its two options into one #71306

Merged
merged 9 commits into from
Jan 31, 2024
3 changes: 3 additions & 0 deletions src/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,9 @@ bool can_butcher_at( const tripoint &p )

bool can_move_vertical_at( const tripoint &p, int movez )
{
if( p.z + movez < -OVERMAP_DEPTH || p.z + movez >= OVERMAP_HEIGHT ) {
return false;
}
Character &player_character = get_player_character();
map &here = get_map();
// TODO: unify this with game::move_vertical
Expand Down
1 change: 0 additions & 1 deletion src/cached_options.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "cached_options.h"

bool fov_3d;
int fov_3d_z_range;
bool keycode_mode;
bool log_from_top;
Expand Down
1 change: 0 additions & 1 deletion src/cached_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
// They should be updated when the corresponding option is changed (in
// options.cpp).

extern bool fov_3d;
extern int fov_3d_z_range;
extern bool keycode_mode;
extern bool log_from_top;
Expand Down
11 changes: 6 additions & 5 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2829,12 +2829,14 @@ float Character::fine_detail_vision_mod( const tripoint &p ) const
float ambient_light{};
tripoint const check_p = p == tripoint_min ? pos() : p;
tripoint const avatar_p = get_avatar().pos();
// Light might not have been calculated on the NPC's z-level
if( is_avatar() || check_p.z == avatar_p.z ||
( fov_3d && std::abs( avatar_p.z - check_p.z ) <= fov_3d_z_range ) ) {
if( is_avatar() || check_p.z == avatar_p.z ) {
ambient_light = std::max( 1.0f,
LIGHT_AMBIENT_LIT - get_map().ambient_light_at( check_p ) + 1.0f );
} else {
// light map is not calculated outside the player character's z-level
// even if fov_3d_z_range > 0, and building light map on multiple levels
// could be expensive, so make NPCs able to see things in this case to
// not interfere with NPC activity.
ambient_light = 1.0f;
}

Expand Down Expand Up @@ -11377,8 +11379,7 @@ bool Character::sees( const Creature &critter ) const
{
// This handles only the player/npc specific stuff (monsters don't have traits or bionics).
const int dist = rl_dist( pos(), critter.pos() );
// No seeing across z-levels with experimental 3D vision disabled
if( !fov_3d && pos().z != critter.pos().z ) {
if( std::abs( pos().z - critter.pos().z ) > fov_3d_z_range ) {
return false;
}
if( dist <= 3 && has_active_mutation( trait_ANTENNAE ) ) {
Expand Down
6 changes: 3 additions & 3 deletions src/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ bool Creature::sees( const Creature &critter ) const
return true;
}

if( !fov_3d && posz() != critter.posz() ) {
if( std::abs( posz() - critter.posz() ) > fov_3d_z_range ) {
return false;
}

Expand Down Expand Up @@ -476,7 +476,7 @@ bool Creature::sees( const Creature &critter ) const

bool Creature::sees( const tripoint &t, bool is_avatar, int range_mod ) const
{
if( !fov_3d && posz() != t.z ) {
if( std::abs( posz() - t.z ) > fov_3d_z_range ) {
return false;
}

Expand Down Expand Up @@ -1370,7 +1370,7 @@ bool Creature::stumble_invis( const Creature &player, const bool stumblemsg )
if( player.has_trait( trait_DEBUG_CLOAK ) ) {
return false;
}
if( !fov_3d && posz() != player.posz() ) {
if( this == &player || !is_adjacent( &player, true ) ) {
return false;
}
if( stumblemsg ) {
Expand Down
2 changes: 1 addition & 1 deletion src/editmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1661,7 +1661,7 @@ bool editmap::move_target( const std::string &action, int moveorigin )
if( eget_direction( mp, action ) ) {
target.x = limited_shift( target.x, mp.x, 0, MAPSIZE_X );
target.y = limited_shift( target.y, mp.y, 0, MAPSIZE_Y );
target.z = limited_shift( target.z, mp.z, -OVERMAP_DEPTH, OVERMAP_HEIGHT + 1 );
target.z = limited_shift( target.z, mp.z, -OVERMAP_DEPTH, OVERMAP_HEIGHT );
if( move_origin ) {
origin += mp;
}
Expand Down
15 changes: 9 additions & 6 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7581,7 +7581,7 @@ look_around_result game::look_around(
ctxt.set_iso( true );
ctxt.register_directions();
ctxt.register_action( "COORDINATE" );
if( change_lv ) {
if( change_lv && fov_3d_z_range > 0 ) {
ctxt.register_action( "LEVEL_UP" );
ctxt.register_action( "LEVEL_DOWN" );
}
Expand Down Expand Up @@ -7615,7 +7615,7 @@ look_around_result game::look_around(

const int old_levz = m.get_abs_sub().z();
const int min_levz = std::max( old_levz - fov_3d_z_range, -OVERMAP_DEPTH );
const int max_levz = std::min( old_levz + fov_3d_z_range, OVERMAP_HEIGHT );
const int max_levz = std::min( old_levz + fov_3d_z_range, OVERMAP_HEIGHT - 1 );

m.update_visibility_cache( old_levz );
const visibility_variables &cache = m.get_visibility_variables_cache();
Expand Down Expand Up @@ -7755,8 +7755,8 @@ look_around_result game::look_around(
}
} else if( action == "LEVEL_UP" || action == "LEVEL_DOWN" ) {
const int dz = action == "LEVEL_UP" ? 1 : -1;
lz = clamp( lz + dz, min_levz, max_levz - 1 );
center.z = clamp( center.z + dz, min_levz, max_levz - 1 );
lz = clamp( lz + dz, min_levz, max_levz );
center.z = clamp( center.z + dz, min_levz, max_levz );

add_msg_debug( debugmode::DF_GAME, "levx: %d, levy: %d, levz: %d",
get_map().get_abs_sub().x(), get_map().get_abs_sub().y(), center.z );
Expand Down Expand Up @@ -11886,8 +11886,11 @@ void game::vertical_move( int movez, bool force, bool peeking )

// TODO: Use u.posz() instead of m.abs_sub
const int z_after = m.get_abs_sub().z() + movez;
if( z_after < -OVERMAP_DEPTH || z_after > OVERMAP_HEIGHT ) {
debugmsg( "Tried to move outside allowed range of z-levels" );
if( z_after < -OVERMAP_DEPTH ) {
add_msg( m_info, _( "Halfway down, the way down becomes blocked off." ) );
return;
} else if( z_after >= OVERMAP_HEIGHT ) {
add_msg( m_info, _( "Halfway up, the way up becomes blocked off." ) );
return;
}

Expand Down
68 changes: 24 additions & 44 deletions src/lightmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1008,53 +1008,33 @@ void map::build_seen_cache( const tripoint &origin, const int target_z, int exte
&camera_cache[0][0], map_dimensions, light_transparency_solid );
}

if( !fov_3d ) {
for( int z = -OVERMAP_DEPTH; z <= OVERMAP_HEIGHT; z++ ) {
level_cache &cur_cache = get_cache( z );
mdarray &cur_out_cache = camera ? cur_cache.camera_cache : cur_cache.seen_cache;
if( z == target_z || cur_cache.seen_cache_dirty ) {
if( !cumulative ) {
std::uninitialized_fill_n(
&cur_out_cache[0][0], map_dimensions, light_transparency_solid );
}
cur_cache.seen_cache_dirty = false;
}

if( z == target_z ) {
out_cache[origin.x][origin.y] = VISIBILITY_FULL;
castLightAll<float, float, sight_calc, sight_check, update_light, accumulate_transparency>(
out_cache, transparency_cache, origin.xy(), penalty );
}
// Cache the caches (pointers to them)
array_of_grids_of<const float> transparency_caches;
array_of_grids_of<float> seen_caches;
array_of_grids_of<const bool> floor_caches;
vertical_direction directions_to_cast = vertical_direction::BOTH;
for( int z = -OVERMAP_DEPTH; z <= OVERMAP_HEIGHT; z++ ) {
level_cache &cur_cache = get_cache( z );
transparency_caches[z + OVERMAP_DEPTH] = &cur_cache.vision_transparency_cache;
seen_caches[z + OVERMAP_DEPTH] = camera ? &cur_cache.camera_cache : &cur_cache.seen_cache;
floor_caches[z + OVERMAP_DEPTH] = &cur_cache.floor_cache;
if( !cumulative ) {
std::uninitialized_fill_n(
&( *seen_caches[z + OVERMAP_DEPTH] )[0][0], map_dimensions, light_transparency_solid );
}
} else {
// Cache the caches (pointers to them)
array_of_grids_of<const float> transparency_caches;
array_of_grids_of<float> seen_caches;
array_of_grids_of<const bool> floor_caches;
vertical_direction directions_to_cast = vertical_direction::BOTH;
for( int z = -OVERMAP_DEPTH; z <= OVERMAP_HEIGHT; z++ ) {
level_cache &cur_cache = get_cache( z );
transparency_caches[z + OVERMAP_DEPTH] = &cur_cache.vision_transparency_cache;
seen_caches[z + OVERMAP_DEPTH] = camera ? &cur_cache.camera_cache : &cur_cache.seen_cache;
floor_caches[z + OVERMAP_DEPTH] = &cur_cache.floor_cache;
if( !cumulative ) {
std::uninitialized_fill_n(
&( *seen_caches[z + OVERMAP_DEPTH] )[0][0], map_dimensions, light_transparency_solid );
}
cur_cache.seen_cache_dirty = false;
if( origin.z == z && cur_cache.no_floor_gaps ) {
directions_to_cast = vertical_direction::UP;
}
}
if( origin.z == target_z ) {
( *seen_caches[ target_z + OVERMAP_DEPTH ] )[origin.x][origin.y] = VISIBILITY_FULL;
cur_cache.seen_cache_dirty = false;
if( origin.z == z && cur_cache.no_floor_gaps ) {
directions_to_cast = vertical_direction::UP;
}

cast_zlight<float, sight_calc, sight_check, accumulate_transparency>(
seen_caches, transparency_caches, floor_caches, origin, penalty, 1.0,
directions_to_cast );
seen_cache_process_ledges( seen_caches, floor_caches, std::nullopt );
}
if( origin.z == target_z ) {
( *seen_caches[ target_z + OVERMAP_DEPTH ] )[origin.x][origin.y] = VISIBILITY_FULL;
}

cast_zlight<float, sight_calc, sight_check, accumulate_transparency>(
seen_caches, transparency_caches, floor_caches, origin, penalty, 1.0,
directions_to_cast );
seen_cache_process_ledges( seen_caches, floor_caches, std::nullopt );

const optional_vpart_position vp = veh_at( origin );
if( !vp ) {
Expand Down
11 changes: 6 additions & 5 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,7 @@ std::set<tripoint_bub_ms> map::get_moving_vehicle_targets( const Creature &z, in
if( !v.v->is_moving() ) {
continue;
}
if( !fov_3d && v.pos.z != zpos.z() ) {
if( std::abs( v.pos.z - zpos.z() ) > fov_3d_z_range ) {
continue;
}
if( rl_dist( zpos, tripoint_bub_ms( v.pos ) ) > max_range + 40 ) {
Expand Down Expand Up @@ -7234,7 +7234,8 @@ point map::sees_cache_key( const tripoint &from, const tripoint &to ) const
bool map::sees( const tripoint &F, const tripoint &T, const int range,
int &bresenham_slope ) const
{
if( ( range >= 0 && range < rl_dist( F, T ) ) ||
if( std::abs( F.z - T.z ) > fov_3d_z_range ||
( range >= 0 && range < rl_dist( F, T ) ) ||
!inbounds( T ) ) {
bresenham_slope = 0;
return false; // Out of range!
Expand All @@ -7247,7 +7248,7 @@ bool map::sees( const tripoint &F, const tripoint &T, const int range,
bool visible = true;

// Ugly `if` for now
if( !fov_3d || F.z == T.z ) {
if( F.z == T.z ) {
bresenham( F.xy(), T.xy(), bresenham_slope,
[this, &visible, &T]( const point & new_point ) {
// Exit before checking the last square, it's still visible even if opaque.
Expand Down Expand Up @@ -7575,11 +7576,11 @@ void map::reachable_flood_steps( std::vector<tripoint> &reachable_pts, const tri
bool map::clear_path( const tripoint &f, const tripoint &t, const int range,
const int cost_min, const int cost_max ) const
{
// Ugly `if` for now
if( !fov_3d && f.z != t.z ) {
if( std::abs( f.z - t.z ) > fov_3d_z_range ) {
return false;
}

// Ugly `if` for now
if( f.z == t.z ) {
if( ( range >= 0 && range < rl_dist( f.xy(), t.xy() ) ) ||
!inbounds( t ) ) {
Expand Down
2 changes: 1 addition & 1 deletion src/melee.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ bool Character::melee_attack( Creature &t, bool allow_special, const matec_id &f
add_msg_if_player( m_info, _( "You lack the substance to affect anything." ) );
return false;
}
if( !is_adjacent( &t, fov_3d ) ) {
if( !is_adjacent( &t, true ) ) {
return false;
}

Expand Down
23 changes: 8 additions & 15 deletions src/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2844,19 +2844,15 @@ void options_manager::add_options_debug()
);

add_empty_line();
add_option_group( "debug", Group( "3dfov_opts", to_translation( "3D Field Of Vision Options" ),
to_translation( "Options regarding 3D field of vision." ) ),
[&]( const std::string & page_id ) {
add( "FOV_3D", page_id, to_translation( "Experimental 3D field of vision" ),
to_translation( "If true and the world is in Z-level mode, the vision will extend beyond current Z-level. If false, vision is limited to current Z-level." ),
false
);

add( "FOV_3D_Z_RANGE", page_id, to_translation( "Vertical range of 3D field of vision" ),
to_translation( "How many levels up and down the experimental 3D field of vision reaches and is drawn on screen. (This many levels up, this many levels down.) 3D vision of the full height of the world can slow the game down a lot. Seeing fewer Z-levels is faster." ),
0, OVERMAP_LAYERS, 4
);
} );
add( "FOV_3D_Z_RANGE", "debug", to_translation( "Vertical range of 3D field of vision" ),
to_translation(
"How many levels up and down the 3D field of vision reaches. (This many levels up, this many levels down.) "
"3D vision of the full height of the world can slow the game down a lot. Seeing fewer Z-levels is faster. "
"Setting this to 0 disables vertical vision. In tiles mode this also affects how many levels up and down are "
"drawn on screen, and setting this to 0 displays only one level below with colored blocks instead." ),
0, OVERMAP_LAYERS, 4
);

add_empty_line();

Expand Down Expand Up @@ -2891,8 +2887,6 @@ void options_manager::add_options_debug()
to_translation( "Maximum distance for auto occlusion handling. Values above zero overwrite tileset settings." ),
0.0, 60.0, 0.0, 0.1
);

get_option( "FOV_3D_Z_RANGE" ).setPrerequisite( "FOV_3D" );
} );
}

Expand Down Expand Up @@ -4035,7 +4029,6 @@ void options_manager::update_options_cache()
log_from_top = ::get_option<std::string>( "LOG_FLOW" ) == "new_top";
message_ttl = ::get_option<int>( "MESSAGE_TTL" );
message_cooldown = ::get_option<int>( "MESSAGE_COOLDOWN" );
fov_3d = ::get_option<bool>( "FOV_3D" );
fov_3d_z_range = ::get_option<int>( "FOV_3D_Z_RANGE" );
keycode_mode = ::get_option<std::string>( "SDL_KEYBOARD_MODE" ) == "keycode";
use_pinyin_search = ::get_option<bool>( "USE_PINYIN_SEARCH" );
Expand Down
39 changes: 18 additions & 21 deletions src/ranged.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,22 +244,6 @@ class target_ui
// List of visible hostile targets
std::vector<Creature *> targets;

// 'true' if map has z levels and 3D fov is on
bool allow_zlevel_shift = false;
// Snap camera to cursor. Can be permanently toggled in settings
// or temporarily in this window
bool snap_to_target = false;
// If true, LEVEL_UP, LEVEL_DOWN and directional keys
// responsible for moving cursor will shift view instead.
bool shifting_view = false;

// Compact layout
bool compact = false;
// Tiny layout - when extremely short on space
bool tiny = false;
// Narrow layout - to keep in theme with
// "compact" and "labels-narrow" sidebar styles.
bool narrow = false;
// Window
catacurses::window w_target;
// Input context
Expand Down Expand Up @@ -295,6 +279,20 @@ class target_ui
// If true, draws turret lines
// relevant for TargetMode::Turrets
bool draw_turret_lines = false;
// Snap camera to cursor. Can be permanently toggled in settings
// or temporarily in this window
bool snap_to_target = false;
// If true, LEVEL_UP, LEVEL_DOWN and directional keys
// responsible for moving cursor will shift view instead.
bool shifting_view = false;

// Compact layout
bool compact = false;
// Tiny layout - when extremely short on space
bool tiny = false;
// Narrow layout - to keep in theme with
// "compact" and "labels-narrow" sidebar styles.
bool narrow = false;

// Create window and set up input context
void init_window_and_input();
Expand Down Expand Up @@ -2464,7 +2462,6 @@ target_handler::trajectory target_ui::run()

map &here = get_map();
// Load settings
allow_zlevel_shift = get_option<bool>( "FOV_3D" );
snap_to_target = get_option<bool>( "SNAP_TO_TARGET" );
if( mode == TargetMode::Turrets ) {
// Due to how cluttered the display would become, disable it by default
Expand Down Expand Up @@ -2756,7 +2753,7 @@ void target_ui::init_window_and_input()
ctxt.register_action( "zoom_out" );
ctxt.register_action( "zoom_in" );
ctxt.register_action( "TOGGLE_MOVE_CURSOR_VIEW" );
if( allow_zlevel_shift ) {
if( fov_3d_z_range > 0 ) {
ctxt.register_action( "LEVEL_UP" );
ctxt.register_action( "LEVEL_DOWN" );
}
Expand Down Expand Up @@ -2864,7 +2861,7 @@ bool target_ui::set_cursor_pos( const tripoint &new_pos )
map &here = get_map();
if( new_pos != src ) {
// On Z axis, make sure we do not exceed map boundaries
valid_pos.z = clamp( valid_pos.z, -OVERMAP_DEPTH, OVERMAP_HEIGHT );
valid_pos.z = clamp( valid_pos.z, -OVERMAP_DEPTH, OVERMAP_HEIGHT - 1 );
// Or current view range
valid_pos.z = clamp( valid_pos.z - src.z, -fov_3d_z_range, fov_3d_z_range ) + src.z;

Expand Down Expand Up @@ -3223,7 +3220,7 @@ void target_ui::cycle_targets( int direction )
void target_ui::set_view_offset( const tripoint &new_offset ) const
{
tripoint new_( new_offset.xy(), clamp( new_offset.z, -fov_3d_z_range, fov_3d_z_range ) );
new_.z = clamp( new_.z + src.z, -OVERMAP_DEPTH, OVERMAP_HEIGHT ) - src.z;
new_.z = clamp( new_.z + src.z, -OVERMAP_DEPTH, OVERMAP_HEIGHT - 1 ) - src.z;

bool changed_z = you->view_offset.z != new_.z;
you->view_offset = new_;
Expand Down Expand Up @@ -3777,7 +3774,7 @@ void target_ui::panel_cursor_info( int &text_y )

std::vector<std::string> labels;
labels.push_back( label_range );
if( allow_zlevel_shift ) {
if( fov_3d_z_range > 0 ) {
labels.push_back( string_format( _( "Elevation: %d" ), dst.z - src.z ) );
}
labels.push_back( string_format( _( "Targets: %d" ), targets.size() ) );
Expand Down
Loading
Loading