diff --git a/data/json/furniture_and_terrain/terrain-liquids.json b/data/json/furniture_and_terrain/terrain-liquids.json index c583d954b01de..0f5907a076959 100644 --- a/data/json/furniture_and_terrain/terrain-liquids.json +++ b/data/json/furniture_and_terrain/terrain-liquids.json @@ -208,6 +208,20 @@ "connects_to": "WATER", "examine_action": "water_source" }, + { + "type": "terrain", + "id": "t_swater_surf", + "name": "surf", + "description": "A broad area of fine sand, washed by waves coming in from the sea.", + "symbol": ".", + "color": "cyan", + "looks_like": "t_swater_sh", + "move_cost": 4, + "connect_groups": [ "SAND", "WATER" ], + "connects_to": [ "SAND", "SANDMOUND", "SANDGLASS", "WATER" ], + "flags": [ "TRANSPARENT", "LIQUID", "NO_SCENT", "SWIMMABLE", "SALT_WATER", "DIGGABLE", "FLAT" ], + "examine_action": "water_source" + }, { "type": "terrain", "id": "t_water_pool", diff --git a/data/json/regional_map_settings.json b/data/json/regional_map_settings.json index 38737e7748005..dfb508cfd109c 100644 --- a/data/json/regional_map_settings.json +++ b/data/json/regional_map_settings.json @@ -362,7 +362,8 @@ "ocean_start_north": 500, "ocean_start_east": 10, "ocean_start_west": 1000, - "ocean_start_south": 0 + "ocean_start_south": 0, + "sandy_beach_width": 6 }, "overmap_ravine_settings": { "num_ravines": 0, "ravine_width": 3, "ravine_range": 45, "ravine_depth": -3 }, "overmap_forest_settings": { diff --git a/data/mods/Backrooms/regional_map_settings.json b/data/mods/Backrooms/regional_map_settings.json index 50b6ad11b338f..c06551141de67 100644 --- a/data/mods/Backrooms/regional_map_settings.json +++ b/data/mods/Backrooms/regional_map_settings.json @@ -62,7 +62,8 @@ "ocean_start_north": 0, "ocean_start_east": 0, "ocean_start_west": 0, - "ocean_start_south": 0 + "ocean_start_south": 0, + "sandy_beach_width": 0 }, "overmap_ravine_settings": { "num_ravines": 0, "ravine_width": 3, "ravine_range": 45, "ravine_depth": -3 }, "overmap_forest_settings": { diff --git a/data/mods/No_Hope/regional_map_settings.json b/data/mods/No_Hope/regional_map_settings.json index fa0996189bbcc..7c5c022ed75eb 100644 --- a/data/mods/No_Hope/regional_map_settings.json +++ b/data/mods/No_Hope/regional_map_settings.json @@ -336,7 +336,8 @@ "ocean_start_north": 500, "ocean_start_east": 10, "ocean_start_west": 1000, - "ocean_start_south": 0 + "ocean_start_south": 0, + "sandy_beach_width": 6 }, "overmap_ravine_settings": { "num_ravines": 0, "ravine_width": 3, "ravine_range": 45, "ravine_depth": -3 }, "overmap_forest_settings": { diff --git a/data/mods/TropiCataclysm/tropical_regional_map_settings.json b/data/mods/TropiCataclysm/tropical_regional_map_settings.json index 0f57269e2c835..078acac0cc2e7 100644 --- a/data/mods/TropiCataclysm/tropical_regional_map_settings.json +++ b/data/mods/TropiCataclysm/tropical_regional_map_settings.json @@ -391,7 +391,8 @@ "ocean_start_north": 500, "ocean_start_east": 10, "ocean_start_west": 1000, - "ocean_start_south": 0 + "ocean_start_south": 0, + "sandy_beach_width": 8 }, "overmap_ravine_settings": { "num_ravines": 0, "ravine_width": 3, "ravine_range": 45, "ravine_depth": -3 }, "overmap_forest_settings": { diff --git a/data/mods/aftershock_exoplanet/region_settings.json b/data/mods/aftershock_exoplanet/region_settings.json index 0ad78c82eb621..c6d9073925294 100644 --- a/data/mods/aftershock_exoplanet/region_settings.json +++ b/data/mods/aftershock_exoplanet/region_settings.json @@ -115,7 +115,8 @@ "ocean_start_north": 0, "ocean_start_east": 0, "ocean_start_west": 0, - "ocean_start_south": 0 + "ocean_start_south": 0, + "sandy_beach_width": 0 }, "overmap_ravine_settings": { "num_ravines": 15, "ravine_width": 3, "ravine_range": 45, "ravine_depth": -3 }, "overmap_forest_settings": { diff --git a/data/mods/classic_zombies/alberta_regional_map_settings.json b/data/mods/classic_zombies/alberta_regional_map_settings.json index 8552552e4550a..4601c5d026a21 100644 --- a/data/mods/classic_zombies/alberta_regional_map_settings.json +++ b/data/mods/classic_zombies/alberta_regional_map_settings.json @@ -320,7 +320,8 @@ "ocean_start_north": 250, "ocean_start_east": 900, "ocean_start_west": 200, - "ocean_start_south": 0 + "ocean_start_south": 0, + "sandy_beach_width": 6 }, "overmap_ravine_settings": { "num_ravines": 0, "ravine_width": 3, "ravine_range": 45, "ravine_depth": -3 }, "overmap_forest_settings": { diff --git a/data/mods/desert_region/desert_regional_map_settings.json b/data/mods/desert_region/desert_regional_map_settings.json index c1c274b64adb8..651d26ae03712 100644 --- a/data/mods/desert_region/desert_regional_map_settings.json +++ b/data/mods/desert_region/desert_regional_map_settings.json @@ -94,7 +94,8 @@ "ocean_start_north": 0, "ocean_start_east": 0, "ocean_start_west": 0, - "ocean_start_south": 0 + "ocean_start_south": 0, + "sandy_beach_width": 0 }, "overmap_ravine_settings": { "num_ravines": 0, "ravine_width": 3, "ravine_range": 15, "ravine_depth": -2 }, "overmap_forest_settings": { diff --git a/data/mods/rural_biome/rural_regional_map_settings.json b/data/mods/rural_biome/rural_regional_map_settings.json index 8ce4e9e7ed887..7b05e57a945e9 100644 --- a/data/mods/rural_biome/rural_regional_map_settings.json +++ b/data/mods/rural_biome/rural_regional_map_settings.json @@ -262,7 +262,8 @@ "ocean_start_north": 500, "ocean_start_east": 10, "ocean_start_west": 1000, - "ocean_start_south": 0 + "ocean_start_south": 0, + "sandy_beach_width": 6 }, "overmap_ravine_settings": { "num_ravines": 0, "ravine_width": 3, "ravine_range": 45, "ravine_depth": -3 }, "overmap_forest_settings": { diff --git a/src/mapdata.cpp b/src/mapdata.cpp index a39cefd7c7389..f1c06b3632dc8 100644 --- a/src/mapdata.cpp +++ b/src/mapdata.cpp @@ -817,7 +817,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_swater_surf, 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, @@ -1068,6 +1068,7 @@ 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_swater_surf = ter_id( "t_swater_surf" ); 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 959ab1cdbf4aa..fa3d44da61fe8 100644 --- a/src/mapdata.h +++ b/src/mapdata.h @@ -767,7 +767,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_swater_surf, 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 15ac16262078b..028481bb4f98f 100644 --- a/src/mapgen_functions.cpp +++ b/src/mapgen_functions.cpp @@ -1918,7 +1918,7 @@ void mapgen_ocean_shore( mapgendata &dat ) const bool w_river_bank = is_river_bank( dat.west() ); // This is length we end up pushing things about by as a baseline. - const int sector_length = SEEX * 2 / 3; + const int sector_length = SEEX - 1; // Define the corners of the map. These won't change. static constexpr point nw_corner{}; @@ -1934,8 +1934,10 @@ void mapgen_ocean_shore( mapgendata &dat ) point sw = sw_corner; std::vector> line_segments; - - // This section is about pushing the straight N, S, E, or W borders inward when adjacent to an actual lake. + int ns_direction_adjust = 0; + int ew_direction_adjust = 0; + int sand_margin = dat.region.overmap_ocean.sandy_beach_width / 2; + // This section is about pushing the straight N, S, E, or W borders inward when adjacent to an actual ocean. if( n_ocean ) { nw.y += sector_length; ne.y += sector_length; @@ -2012,13 +2014,18 @@ void mapgen_ocean_shore( mapgendata &dat ) if( w_river_bank ) { line_segments.push_back( { sw, w } ); + ns_direction_adjust += sand_margin; + ew_direction_adjust -= sand_margin; } if( n_river_bank ) { line_segments.push_back( { n, ne } ); + ns_direction_adjust -= sand_margin; + ew_direction_adjust += sand_margin; } - line_segments.push_back( { n, w } ); + ns_direction_adjust -= sand_margin; + ew_direction_adjust -= sand_margin; } } @@ -2038,13 +2045,19 @@ void mapgen_ocean_shore( mapgendata &dat ) if( e_river_bank ) { line_segments.push_back( { se, e } ); + ns_direction_adjust += sand_margin; + ew_direction_adjust += sand_margin; } if( n_river_bank ) { line_segments.push_back( { n, nw } ); + ns_direction_adjust -= sand_margin; + ew_direction_adjust -= sand_margin; } line_segments.push_back( { n, e } ); + ns_direction_adjust -= sand_margin; + ew_direction_adjust += sand_margin; } } @@ -2064,13 +2077,18 @@ void mapgen_ocean_shore( mapgendata &dat ) if( w_river_bank ) { line_segments.push_back( { nw, w } ); + ns_direction_adjust -= sand_margin; + ew_direction_adjust -= sand_margin; } if( s_river_bank ) { line_segments.push_back( { s, se } ); + ns_direction_adjust += sand_margin; + ew_direction_adjust += sand_margin; } - line_segments.push_back( { s, w } ); + ns_direction_adjust += sand_margin; + ew_direction_adjust -= sand_margin; } } @@ -2090,13 +2108,19 @@ void mapgen_ocean_shore( mapgendata &dat ) if( e_river_bank ) { line_segments.push_back( { ne, e } ); + ns_direction_adjust -= sand_margin; + ew_direction_adjust += sand_margin; } if( s_river_bank ) { line_segments.push_back( { s, sw } ); + ns_direction_adjust += sand_margin; + ew_direction_adjust -= sand_margin; } line_segments.push_back( { s, e } ); + ns_direction_adjust += sand_margin; + ew_direction_adjust += sand_margin; } } @@ -2105,19 +2129,24 @@ void mapgen_ocean_shore( mapgendata &dat ) // at the map boundaries, but have subsequently been perturbed by the adjacent terrains. // Let's look at them and see which ones differ from their original state and should // form our shoreline. + if( nw.y != nw_corner.y || ne.y != ne_corner.y ) { + ns_direction_adjust -= sand_margin * 2; line_segments.push_back( { nw, ne } ); } if( ne.x != ne_corner.x || se.x != se_corner.x ) { + ew_direction_adjust += sand_margin * 2; line_segments.push_back( { ne, se } ); } if( se.y != se_corner.y || sw.y != sw_corner.y ) { + ns_direction_adjust += sand_margin * 2; line_segments.push_back( { se, sw } ); } if( sw.x != sw_corner.x || nw.x != nw_corner.x ) { + ew_direction_adjust -= sand_margin * 2; line_segments.push_back( { sw, nw } ); } @@ -2127,24 +2156,59 @@ void mapgen_ocean_shore( mapgendata &dat ) // It buffers the points a bit for a thicker line. It also clears any furniture that might // be in the location as a result of our extending adjacent mapgen. const auto draw_shallow_water = [&]( const point & from, const point & to ) { + point from_mod = from; + point to_mod = to; + if( from.x != 0 && from.x != SEEX * 2 - 1 ) { + from_mod.x += ew_direction_adjust; + } + if( from.y != 0 && from.y != SEEX * 2 - 1 ) { + from_mod.y += ns_direction_adjust; + } + if( to.x != 0 && to.x != SEEX * 2 - 1 ) { + to_mod.x += ew_direction_adjust; + } + if( to.y != 0 && to.y != SEEX * 2 - 1 ) { + to_mod.y += ns_direction_adjust; + } + std::vector points = line_to( from_mod, to_mod ); + for( point &p : points ) { + for( const point &bp : closest_points_first( p, sand_margin ) ) { + if( !map_boundaries.contains( bp ) ) { + continue; + } + m->ter_set( bp, t_swater_sh ); + m->furn_set( bp, f_null ); + } + } + }; + // This will draw our sandy beach coastline from the "from" point to the "to" point. + const auto draw_sand = [&]( const point & from, const point & to ) { std::vector points = line_to( from, to ); for( point &p : points ) { - for( const point &bp : closest_points_first( p, 1 ) ) { + for( const point &bp : closest_points_first( p, sand_margin ) ) { if( !map_boundaries.contains( bp ) ) { continue; } - // Use t_null for now instead of t_water_sh, because sometimes our extended terrain - // has put down a t_water_sh, and we need to be able to flood-fill over that. + // Use t_null for now instead of t_sand, because sometimes our extended terrain + // has put down a t_sand, and we need to be able to flood-fill over that. m->ter_set( bp, t_null ); m->furn_set( bp, f_null ); } + for( const point &bp : closest_points_first( p, sand_margin + 1 ) ) { + if( !map_boundaries.contains( bp ) ) { + continue; + } + if( m->ter( bp ) == t_swater_sh ) { + m->ter_set( bp, t_swater_surf ); + } + } } }; // 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 = [&]( const point & from, const point & to ) { - const int jitter = rl_dist( from, to ) / 4; + const int jitter = rl_dist( from, to ) / 5; const point midpoint( ( from.x + to.x ) / 2 + rng( -jitter, jitter ), ( from.y + to.y ) / 2 + rng( -jitter, jitter ) ); return midpoint; @@ -2152,7 +2216,9 @@ void mapgen_ocean_shore( mapgendata &dat ) // 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. + // midpoints. + // Draw water after the sand to make sure we don't get too much sand. Everyone hates sand, + // it's coarse and - you know what, never mind. for( auto &ls : line_segments ) { const point mp1 = jittered_midpoint( ls[0], ls[1] ); const point mp2 = jittered_midpoint( ls[0], mp1 ); @@ -2162,6 +2228,10 @@ void mapgen_ocean_shore( mapgendata &dat ) draw_shallow_water( mp2, mp1 ); draw_shallow_water( mp1, mp3 ); draw_shallow_water( mp3, ls[1] ); + draw_sand( ls[0], mp2 ); + draw_sand( mp2, mp1 ); + draw_sand( mp1, mp3 ); + draw_sand( mp3, ls[1] ); } // Now that we've done our ground mapgen and laid down a contiguous shoreline of shallow water, @@ -2173,7 +2243,7 @@ void mapgen_ocean_shore( mapgendata &dat ) if( !map_boundaries.contains( p ) ) { return false; } - return m->ter( p ) != t_null; + return m->ter( p ) != t_null && m->ter( p ) != t_swater_sh && m->ter( p ) != t_swater_surf; }; const auto fill_deep_water = [&]( const point & starting_point ) { @@ -2203,9 +2273,9 @@ void mapgen_ocean_shore( mapgendata &dat ) fill_deep_water( se_corner ); } - // 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_swater_sh. - m->translate( t_null, t_swater_sh ); + // We previously placed our sand but actually did a t_null instead to make sure that we didn't + // pick up sand from our extended terrain. Now turn those nulls into t_sand. + m->translate( t_null, t_sand ); } void mapgen_ravine_edge( mapgendata &dat ) diff --git a/src/regional_settings.cpp b/src/regional_settings.cpp index 830de2eba4f05..5d11eb45e24b0 100644 --- a/src/regional_settings.cpp +++ b/src/regional_settings.cpp @@ -393,6 +393,8 @@ static void load_overmap_ocean_settings( const JsonObject &jo, overmap_ocean_settings.ocean_start_west, !overlay ); read_and_set_or_throw( overmap_ocean_settings_jo, "ocean_start_south", overmap_ocean_settings.ocean_start_south, !overlay ); + read_and_set_or_throw( overmap_ocean_settings_jo, "sandy_beach_width", + overmap_ocean_settings.sandy_beach_width, !overlay ); } } diff --git a/src/regional_settings.h b/src/regional_settings.h index c254a0c64e334..0a6d471502d61 100644 --- a/src/regional_settings.h +++ b/src/regional_settings.h @@ -219,6 +219,7 @@ struct overmap_ocean_settings { int ocean_start_east = 10; int ocean_start_west = 0; int ocean_start_south = 0; + int sandy_beach_width = 2; overmap_ocean_settings() = default; };