diff --git a/data/json/furniture_and_terrain/terrain-doors.json b/data/json/furniture_and_terrain/terrain-doors.json index 76be3f1cb4728..bdde12b9396dd 100644 --- a/data/json/furniture_and_terrain/terrain-doors.json +++ b/data/json/furniture_and_terrain/terrain-doors.json @@ -3086,7 +3086,7 @@ "connect_groups": "WALL", "connects_to": "WALL", "rotates_to": "INDOORFLOOR", - "flags": [ "DOOR", "NOITEM", "BLOCK_WIND", "SUPPORTS_ROOF" ], + "flags": [ "DOOR", "NOITEM", "BLOCK_WIND", "SUPPORTS_ROOF", "TRANSLUCENT" ], "open": "t_door_glass_frosted_o", "copy-from": "t_door_glass_c" }, @@ -3101,7 +3101,7 @@ "connect_groups": "WALL", "connects_to": "WALL", "rotates_to": "INDOORFLOOR", - "flags": [ "DOOR", "NOITEM", "SUPPORTS_ROOF" ], + "flags": [ "DOOR", "NOITEM", "SUPPORTS_ROOF", "TRANSLUCENT" ], "open": "t_door_glass_frosted_lab_o", "copy-from": "t_door_glass_frosted_c" }, diff --git a/data/json/furniture_and_terrain/terrain-windows.json b/data/json/furniture_and_terrain/terrain-windows.json index ed5807bf18ec9..7f324b5690b2f 100644 --- a/data/json/furniture_and_terrain/terrain-windows.json +++ b/data/json/furniture_and_terrain/terrain-windows.json @@ -1019,6 +1019,7 @@ "BLOCK_WIND", "REDUCE_SCENT", "WINDOW", + "TRANSLUCENT", "SUPPORTS_ROOF" ], "bash": { @@ -1051,6 +1052,7 @@ "BLOCK_WIND", "REDUCE_SCENT", "WINDOW", + "TRANSLUCENT", "SUPPORTS_ROOF" ], "bash": { @@ -1083,6 +1085,7 @@ "BLOCK_WIND", "REDUCE_SCENT", "WINDOW", + "TRANSLUCENT", "SUPPORTS_ROOF" ], "bash": { diff --git a/doc/JSON_FLAGS.md b/doc/JSON_FLAGS.md index 721a508f1aa22..c28d168c0870b 100644 --- a/doc/JSON_FLAGS.md +++ b/doc/JSON_FLAGS.md @@ -701,6 +701,7 @@ List of known flags, used in both `furniture` and `terrain`. Some work for both - ```TRANSLOCATOR``` Tile is a translocator gate, for purposes of the `translocator` examine action. - ```TRANSPARENT_FLOOR``` This terrain allows light to the z-level below. - ```TRANSPARENT``` Players and monsters can see through/past it. Also sets ter_t.transparent. +- ```TRANSLUCENT``` Player and monsters can't see through/past it, but it can pass the light - ```UNSTABLE``` Walking here cause the bouldering effect on the character. - ```USABLE_FIRE``` This terrain or furniture counts as a nearby fire for crafting. - ```WALL``` This terrain is an upright obstacle. Used for fungal conversion, and also implies `CONNECT_WITH_WALL`. diff --git a/src/lightmap.cpp b/src/lightmap.cpp index b1181d08d22e4..09fa685e2c830 100644 --- a/src/lightmap.cpp +++ b/src/lightmap.cpp @@ -152,7 +152,8 @@ bool map::build_transparency_cache( const int zlev ) // Fields are either transparent or not, however we want some to be translucent value = value * i_level.translucency; } - // TODO: [lightmap] Have glass reduce light as well + // TODO: [lightmap] Have glass reduce light as well. + // Note, binary transluceny is implemented in build_vision_transparency_cache below return std::make_pair( value, value_wo_fields ); }; @@ -208,6 +209,8 @@ bool map::build_vision_transparency_cache( const int zlev ) bool dirty = false; + // This segment handles vision when the player is crouching or prone. It only checks adjacent tiles. + // If you change this, also consider creature::sees and map::obstacle_coverage. bool is_crouching = player_character.is_crouching(); bool low_profile = player_character.has_effect( effect_quadruped_full ) && player_character.is_running(); @@ -229,6 +232,17 @@ bool map::build_vision_transparency_cache( const int zlev ) } } + // This segment handles blocking vision through TRANSLUCENT flagged terrain. + for( const tripoint &loc : points_in_radius( p, MAX_VIEW_DISTANCE ) ) { + if( loc == p ) { + // The tile player is standing on should always be visible + vision_transparency_cache[p.x][p.y] = LIGHT_TRANSPARENCY_OPEN_AIR; + } else if( map::ter( loc ).obj().has_flag( ter_furn_flag::TFLAG_TRANSLUCENT ) ) { + vision_transparency_cache[loc.x][loc.y] = LIGHT_TRANSPARENCY_SOLID; + dirty = true; + } + } + return dirty; } diff --git a/src/mapdata.cpp b/src/mapdata.cpp index b275474b9caf0..d74430bcec3d2 100644 --- a/src/mapdata.cpp +++ b/src/mapdata.cpp @@ -260,8 +260,9 @@ std::string enum_to_string( ter_furn_flag data ) case ter_furn_flag::TFLAG_TRANSPARENT_FLOOR: return "TRANSPARENT_FLOOR"; case ter_furn_flag::TFLAG_TOILET_WATER: return "TOILET_WATER"; case ter_furn_flag::TFLAG_ELEVATOR: return "ELEVATOR"; - case ter_furn_flag::TFLAG_ACTIVE_GENERATOR: return "ACTIVE_GENERATOR"; - case ter_furn_flag::TFLAG_NO_FLOOR_WATER: return "NO_FLOOR_WATER"; + case ter_furn_flag::TFLAG_ACTIVE_GENERATOR: return "ACTIVE_GENERATOR"; + case ter_furn_flag::TFLAG_TRANSLUCENT: return "TRANSLUCENT"; + case ter_furn_flag::TFLAG_NO_FLOOR_WATER: return "NO_FLOOR_WATER"; case ter_furn_flag::TFLAG_GRAZABLE: return "GRAZABLE"; case ter_furn_flag::TFLAG_GRAZER_INEDIBLE: return "GRAZER_INEDIBLE"; case ter_furn_flag::TFLAG_BROWSABLE: return "BROWSABLE"; @@ -679,7 +680,8 @@ void load_terrain( const JsonObject &jo, const std::string &src ) void map_data_common_t::extraprocess_flags( const ter_furn_flag flag ) { - if( !transparent && flag == ter_furn_flag::TFLAG_TRANSPARENT ) { + if( !transparent && ( flag == ter_furn_flag::TFLAG_TRANSPARENT || + flag == ter_furn_flag::TFLAG_TRANSLUCENT ) ) { transparent = true; } diff --git a/src/mapdata.h b/src/mapdata.h index 035435401ab10..917fd4afcdb83 100644 --- a/src/mapdata.h +++ b/src/mapdata.h @@ -134,6 +134,7 @@ struct plant_data { /* * List of known flags, used in both terrain.json and furniture.json. * TRANSPARENT - Players and monsters can see through/past it. Also sets ter_t.transparent + * TRANSLUCENT - Must be paired with TRANSPARENT. Allows light to pass through, but blocks vision. * FLAT - Player can build and move furniture on * CONTAINER - Items on this square are hidden until looted by the player * PLACE_ITEM - Valid terrain for place_item() to put items on @@ -201,6 +202,7 @@ struct plant_data { */ enum class ter_furn_flag : int { TFLAG_TRANSPARENT, + TFLAG_TRANSLUCENT, TFLAG_FLAMMABLE, TFLAG_REDUCE_SCENT, TFLAG_SWIMMABLE, diff --git a/tests/vision_test.cpp b/tests/vision_test.cpp index 613576dc2b36b..bcd39f68a6be2 100644 --- a/tests/vision_test.cpp +++ b/tests/vision_test.cpp @@ -45,6 +45,7 @@ static const ter_str_id ter_t_flat_roof( "t_flat_roof" ); static const ter_str_id ter_t_floor( "t_floor" ); static const ter_str_id ter_t_utility_light( "t_utility_light" ); static const ter_str_id ter_t_window_frame( "t_window_frame" ); +static const ter_str_id ter_t_window_stained_green( "t_window_stained_green" ); static const trait_id trait_MYOPIC( "MYOPIC" ); @@ -125,6 +126,7 @@ static const tile_predicate set_up_tiles_common = ifchar( '#', ter_set( ter_t_brick_wall ) + ter_set_flat_roof_above ) || ifchar( '=', ter_set( ter_t_window_frame ) + ter_set_flat_roof_above ) || ifchar( '-', ter_set( ter_t_floor ) + ter_set_flat_roof_above ) || + ifchar( 'G', ter_set( ter_t_window_stained_green ) + ter_set_flat_roof_above ) || fail; struct vision_test_flags { @@ -424,6 +426,27 @@ TEST_CASE( "vision_crouching_blocks_vision_but_not_light", "[shadowcasting][visi t.test_all(); } +TEST_CASE( "vision_translucent_blocks_vision_but_not_light", "[shadowcasting][vision]" ) +{ + vision_test_case t{ + { + "###", + "#u#", + "#G#", + " ", + }, + { + "444", + "444", + "444", + "666", + }, + day_time + }; + + t.test_all(); +} + TEST_CASE( "vision_see_wall_in_moonlight", "[shadowcasting][vision]" ) { const time_point full_moon = calendar::turn_zero + calendar::season_length() / 6;