From dbfd88d96ccfa5e38ec2a1c0aabce63f8bb7649b Mon Sep 17 00:00:00 2001 From: Vollch Date: Mon, 18 Dec 2023 03:43:08 +0300 Subject: [PATCH] feat: smooth underwater shore (#3938) * Underwater shore * Shut up linter --- .../overmap_terrain_waterbody.json | 11 ++++++++ src/mapdata.cpp | 4 ++- src/mapdata.h | 2 +- src/mapgen_functions.cpp | 27 +++++++++++++++---- src/mapgendata.cpp | 4 +-- src/mapgendata.h | 5 ++-- src/overmap.cpp | 5 ++++ 7 files changed, 46 insertions(+), 12 deletions(-) diff --git a/data/json/overmap/overmap_terrain/overmap_terrain_waterbody.json b/data/json/overmap/overmap_terrain/overmap_terrain_waterbody.json index 79330a61707c..ae6bb1d99912 100644 --- a/data/json/overmap/overmap_terrain/overmap_terrain_waterbody.json +++ b/data/json/overmap/overmap_terrain/overmap_terrain_waterbody.json @@ -10,6 +10,17 @@ "flags": [ "NO_ROTATE", "LAKE_SHORE", "SOURCE_DRINK" ], "mapgen": [ { "method": "builtin", "name": "lake_shore" } ] }, + { + "type": "overmap_terrain", + "id": "lake_underwater_shore", + "copy-from": "generic_water", + "name": "lake shore (submerged)", + "sym": "#", + "color": "light_blue", + "see_cost": 1, + "flags": [ "NO_ROTATE", "LAKE_SHORE", "SOURCE_DRINK" ], + "mapgen": [ { "method": "builtin", "name": "lake_shore" } ] + }, { "type": "overmap_terrain", "id": "lake_surface", diff --git a/src/mapdata.cpp b/src/mapdata.cpp index 8163e73b861d..a14042f658ce 100644 --- a/src/mapdata.cpp +++ b/src/mapdata.cpp @@ -697,7 +697,7 @@ ter_id t_null, t_fungus_mound, t_fungus, t_shrub_fungal, t_tree_fungal, t_tree_fungal_young, t_marloss_tree, // Water, lava, etc. t_water_moving_dp, t_water_moving_sh, t_water_sh, t_water_dp, t_swater_sh, t_swater_dp, - t_water_pool, t_sewage, + t_water_cube, t_lake_bed, t_water_pool, t_sewage, t_lava, // More embellishments than you can shake a stick at. t_sandbox, t_slide, t_monkey_bars, t_backboard, @@ -948,6 +948,8 @@ void set_ter_ids() t_water_dp = ter_id( "t_water_dp" ); t_swater_sh = ter_id( "t_swater_sh" ); t_swater_dp = ter_id( "t_swater_dp" ); + t_water_cube = ter_id( "t_water_cube" ); + t_lake_bed = ter_id( "t_lake_bed" ); t_water_pool = ter_id( "t_water_pool" ); t_sewage = ter_id( "t_sewage" ); t_lava = ter_id( "t_lava" ); diff --git a/src/mapdata.h b/src/mapdata.h index a8bddeca7121..ba8ee7878380 100644 --- a/src/mapdata.h +++ b/src/mapdata.h @@ -711,7 +711,7 @@ extern ter_id t_null, t_fungus_mound, t_fungus, t_shrub_fungal, t_tree_fungal, t_tree_fungal_young, t_marloss_tree, // Water, lava, etc. t_water_moving_dp, t_water_moving_sh, t_water_sh, t_swater_sh, t_water_dp, t_swater_dp, - t_water_pool, t_sewage, + t_water_cube, t_lake_bed, t_water_pool, t_sewage, t_lava, // More embellishments than you can shake a stick at. t_sandbox, t_slide, t_monkey_bars, t_backboard, diff --git a/src/mapgen_functions.cpp b/src/mapgen_functions.cpp index ea71099752f9..d3fb2eccf643 100644 --- a/src/mapgen_functions.cpp +++ b/src/mapgen_functions.cpp @@ -16,6 +16,7 @@ #include "enums.h" #include "field_type.h" #include "flood_fill.h" +#include "game.h" #include "game_constants.h" #include "int_id.h" #include "line.h" @@ -2587,7 +2588,11 @@ void mapgen_lake_shore( mapgendata &dat ) // If we didn't extend an adjacent terrain, then just fill this entire location with the default // groundcover for the region. if( !did_extend_adjacent_terrain ) { - dat.fill_groundcover(); + if( dat.zlevel() >= 0 ) { + dat.fill_groundcover(); + } else { + fill_background( m, t_rock ); + } } const oter_id river_center( "river_center" ); @@ -2867,15 +2872,27 @@ void mapgen_lake_shore( mapgendata &dat ) } }; + // We need to have same shoreline on different z levels, to match surface shore + // with submerged shore, to do so we'll jitter shore lines using deterministic + // random seeded with x\y coordinates + // NOLINTNEXTLINE(cata-determinism) + std::mt19937 prng( std::hash()( dat.pos.xy() ) ^ g->get_seed() ); + // Given two points, return a point that is midway between the two points and then // jittered by a random amount in proportion to the length of the line segment. const auto jittered_midpoint = [&]( point from, point to ) { const int jitter = rl_dist( from, to ) / 4; - const point midpoint( ( from.x + to.x ) / 2 + rng( -jitter, jitter ), - ( from.y + to.y ) / 2 + rng( -jitter, jitter ) ); + std::uniform_int_distribution roll( -jitter, jitter ); + const point midpoint( ( from.x + to.x ) / 2 + roll( prng ), + ( from.y + to.y ) / 2 + roll( prng ) ); return midpoint; }; + ter_id edge_tile = dat.zlevel() >= 0 ? t_water_sh : t_rock; + ter_id water_tile = dat.zlevel() >= 0 ? t_water_dp : + dat.zlevel() == dat.region.overmap_lake.lake_depth ? t_lake_bed : + t_water_cube; + // For each of our valid shoreline line segments, generate a slightly more interesting // set of line segments by splitting the line into four segments with jittered // midpoints, and then draw shallow water for four each of those. @@ -2906,7 +2923,7 @@ void mapgen_lake_shore( mapgendata &dat ) std::vector water_points = ff::point_flood_fill_4_connected( starting_point, visited, should_fill ); for( auto &wp : water_points ) { - m->ter_set( wp, t_water_dp ); + m->ter_set( wp, water_tile ); m->furn_set( wp, f_null ); } }; @@ -2931,7 +2948,7 @@ void mapgen_lake_shore( mapgendata &dat ) // We previously placed our shallow water but actually did a t_null instead to make sure that we didn't // pick up shallow water from our extended terrain. Now turn those nulls into t_water_sh. - m->translate( t_null, t_water_sh ); + m->translate( t_null, edge_tile ); } void mremove_trap( map *m, point p ) diff --git a/src/mapgendata.cpp b/src/mapgendata.cpp index 9f10689af562..3e84cf7f0b22 100644 --- a/src/mapgendata.cpp +++ b/src/mapgendata.cpp @@ -34,7 +34,7 @@ mapgendata::mapgendata( map &mp, dummy_settings_t ) : density_( 0 ) , when_( calendar::turn ) , mission_( nullptr ) - , zlevel_( 0 ) + , pos( tripoint_zero ) , region( dummy_regional_settings ) , m( mp ) , default_groundcover( region.default_groundcover ) @@ -50,9 +50,9 @@ mapgendata::mapgendata( const tripoint_abs_omt &over, map &mp, const float densi , density_( density ) , when_( when ) , mission_( miss ) - , zlevel_( over.z() ) , t_above( overmap_buffer.ter( over + tripoint_above ) ) , t_below( overmap_buffer.ter( over + tripoint_below ) ) + , pos( over ) , region( overmap_buffer.get_settings( over ) ) , m( mp ) , default_groundcover( region.default_groundcover ) diff --git a/src/mapgendata.h b/src/mapgendata.h index 2f02e747ed05..6f79b9581c78 100644 --- a/src/mapgendata.h +++ b/src/mapgendata.h @@ -69,7 +69,6 @@ class mapgendata float density_; time_point when_; ::mission *mission_; - int zlevel_; mapgen_arguments mapgen_args_; public: @@ -89,6 +88,7 @@ class mapgendata std::unordered_map joins; + const tripoint_abs_omt pos; const regional_settings ®ion; map &m; @@ -135,8 +135,7 @@ class mapgendata return mission_; } int zlevel() const { - // TODO: should be able to determine this from the map itself - return zlevel_; + return pos.z(); } void set_dir( int dir_in, int val ); diff --git a/src/overmap.cpp b/src/overmap.cpp index 861d2bf13c42..f254fe509d9c 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -4100,6 +4100,7 @@ void overmap::place_lakes() const oter_id lake_surface( "lake_surface" ); const oter_id lake_shore( "lake_shore" ); + const oter_id lake_underwater_shore( "lake_underwater_shore" ); const oter_id lake_water_cube( "lake_water_cube" ); const oter_id lake_bed( "lake_bed" ); @@ -4178,6 +4179,10 @@ void overmap::place_lakes() ter_set( tripoint_om_omt( p, z ), lake_water_cube ); } ter_set( tripoint_om_omt( p, settings->overmap_lake.lake_depth ), lake_bed ); + } else { + for( int z = -1; z >= settings->overmap_lake.lake_depth; z-- ) { + ter_set( tripoint_om_omt( p, z ), lake_underwater_shore ); + } } }