diff --git a/data/json/items/comestibles/egg.json b/data/json/items/comestibles/egg.json index cb963f2a8736f..7adf95f75de40 100644 --- a/data/json/items/comestibles/egg.json +++ b/data/json/items/comestibles/egg.json @@ -522,6 +522,76 @@ "copy-from": "egg_fish", "rot_spawn": "GROUP_EGG_SALMON" }, + { + "type": "COMESTIBLE", + "id": "egg_cod", + "name": { "str_sp": "roe" }, + "copy-from": "egg_fish", + "rot_spawn": "GROUP_EGG_COD" + }, + { + "type": "COMESTIBLE", + "id": "egg_haddock", + "name": { "str_sp": "roe" }, + "copy-from": "egg_fish", + "rot_spawn": "GROUP_EGG_HADDOCK" + }, + { + "type": "COMESTIBLE", + "id": "egg_bluefin_tuna", + "name": { "str_sp": "roe" }, + "copy-from": "egg_fish", + "rot_spawn": "GROUP_EGG_BLUEFIN_TUNA" + }, + { + "type": "COMESTIBLE", + "id": "egg_halibut", + "name": { "str_sp": "roe" }, + "copy-from": "egg_fish", + "rot_spawn": "GROUP_EGG_HALIBUT" + }, + { + "type": "COMESTIBLE", + "id": "egg_pollock", + "name": { "str_sp": "roe" }, + "copy-from": "egg_fish", + "rot_spawn": "GROUP_EGG_POLLOCK" + }, + { + "type": "COMESTIBLE", + "id": "egg_flounder", + "name": { "str_sp": "roe" }, + "copy-from": "egg_fish", + "rot_spawn": "GROUP_EGG_FLOUNDER" + }, + { + "type": "COMESTIBLE", + "id": "egg_mackerel", + "name": { "str_sp": "roe" }, + "copy-from": "egg_fish", + "rot_spawn": "GROUP_EGG_MACKEREL" + }, + { + "type": "COMESTIBLE", + "id": "egg_bluefish", + "name": { "str_sp": "roe" }, + "copy-from": "egg_fish", + "rot_spawn": "GROUP_EGG_BLUEFISH" + }, + { + "type": "COMESTIBLE", + "id": "egg_blackfish", + "name": { "str_sp": "roe" }, + "copy-from": "egg_fish", + "rot_spawn": "GROUP_EGG_BLACKFISH" + }, + { + "type": "COMESTIBLE", + "id": "egg_porgy", + "name": { "str_sp": "roe" }, + "copy-from": "egg_fish", + "rot_spawn": "GROUP_EGG_PORGY" + }, { "type": "COMESTIBLE", "id": "egg_kokanee_salmon", diff --git a/data/json/monstergroups/eggs.json b/data/json/monstergroups/eggs.json index 93e4fc51c4a35..47a3deff4caee 100644 --- a/data/json/monstergroups/eggs.json +++ b/data/json/monstergroups/eggs.json @@ -311,6 +311,56 @@ "type": "monstergroup", "monsters": [ { "monster": "mon_fry_salmon" } ] }, + { + "name": "GROUP_EGG_COD", + "type": "monstergroup", + "monsters": [ { "monster": "mon_fry_cod" } ] + }, + { + "name": "GROUP_EGG_HADDOCK", + "type": "monstergroup", + "monsters": [ { "monster": "mon_fry_haddock" } ] + }, + { + "name": "GROUP_EGG_BLUEFIN_TUNA", + "type": "monstergroup", + "monsters": [ { "monster": "mon_fry_bluefin_tuna" } ] + }, + { + "name": "GROUP_EGG_HALIBUT", + "type": "monstergroup", + "monsters": [ { "monster": "mon_fry_halibut" } ] + }, + { + "name": "GROUP_EGG_POLLOCK", + "type": "monstergroup", + "monsters": [ { "monster": "mon_fry_pollock" } ] + }, + { + "name": "GROUP_EGG_FLOUNDER", + "type": "monstergroup", + "monsters": [ { "monster": "mon_fry_flounder" } ] + }, + { + "name": "GROUP_EGG_MACKEREL", + "type": "monstergroup", + "monsters": [ { "monster": "mon_fry_mackerel" } ] + }, + { + "name": "GROUP_EGG_BLUEFISH", + "type": "monstergroup", + "monsters": [ { "monster": "mon_fry_bluefish" } ] + }, + { + "name": "GROUP_EGG_BLACKFISH", + "type": "monstergroup", + "monsters": [ { "monster": "mon_fry_blackfish" } ] + }, + { + "name": "GROUP_EGG_PORGY", + "type": "monstergroup", + "monsters": [ { "monster": "mon_fry_porgy" } ] + }, { "name": "GROUP_EGG_KOKANEE_SALMON", "type": "monstergroup", diff --git a/data/json/monstergroups/wilderness.json b/data/json/monstergroups/wilderness.json index 8fcacbba1d58f..d6c10d9f2a1c1 100644 --- a/data/json/monstergroups/wilderness.json +++ b/data/json/monstergroups/wilderness.json @@ -342,7 +342,7 @@ { "monster": "mon_fish_sbass", "weight": 10, "cost_multiplier": 3, "pack_size": [ 1, 3 ] }, { "monster": "mon_fish_perch", "weight": 10, "cost_multiplier": 3, "pack_size": [ 1, 3 ] }, { "monster": "mon_fish_salmon", "weight": 6, "cost_multiplier": 8, "pack_size": [ 4, 6 ] }, - { "monster": "mon_fish_lbass", "weight": 10, "cost_multiplier": 3, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_lbass", "weight": 6, "cost_multiplier": 3, "pack_size": [ 1, 3 ] }, { "monster": "mon_fish_pbass", "weight": 10, "cost_multiplier": 3, "pack_size": [ 1, 3 ] }, { "monster": "mon_fish_bluegill", "weight": 10, "cost_multiplier": 3, "pack_size": [ 1, 3 ] }, { "monster": "mon_fish_whitefish", "weight": 10, "cost_multiplier": 2, "pack_size": [ 4, 6 ] }, @@ -378,6 +378,44 @@ { "group": "GROUP_MUTAFROGS_RIVER", "weight": 8, "starts": "7 days" } ] }, + { + "type": "monstergroup", + "name": "GROUP_OCEAN_SHORE", + "default": "mon_null", + "is_animal": true, + "monsters": [ + { "monster": "mon_ocean_zhark", "weight": 2, "cost_multiplier": 25, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_eel", "weight": 6, "cost_multiplier": 3, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_pbass", "weight": 10, "cost_multiplier": 3, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_bluefish", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_blackfish", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_porgy", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_flounder", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_mackerel", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_salmon", "weight": 6, "cost_multiplier": 8, "pack_size": [ 4, 6 ] } + ] + }, + { + "type": "monstergroup", + "name": "GROUP_OCEAN_DEEP", + "default": "mon_null", + "is_animal": true, + "monsters": [ + { "monster": "mon_ocean_zhark", "weight": 4, "cost_multiplier": 25, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_cod", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_haddock", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_bluefin_tuna", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_halibut", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_pollock", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_flounder", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_mackerel", "weight": 6, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_salmon", "weight": 6, "cost_multiplier": 8, "pack_size": [ 4, 6 ] }, + { "monster": "mon_fish_pbass", "weight": 5, "cost_multiplier": 3, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_bluefish", "weight": 3, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_blackfish", "weight": 3, "cost_multiplier": 8, "pack_size": [ 1, 3 ] }, + { "monster": "mon_fish_porgy", "weight": 3, "cost_multiplier": 8, "pack_size": [ 1, 3 ] } + ] + }, { "type": "monstergroup", "name": "GROUP_SWAMP", diff --git a/data/json/monsters/fish.json b/data/json/monsters/fish.json index d204a49465bb5..a9592cf2237fe 100644 --- a/data/json/monsters/fish.json +++ b/data/json/monsters/fish.json @@ -1233,5 +1233,176 @@ "baby_flags": [ "SPRING", "SUMMER", "AUTUMN", "WINTER" ], "path_settings": { "max_dist": 5 }, "flags": [ "SEES", "SMELLS", "AQUATIC" ] + }, + { + "id": "mon_fish_mackerel", + "type": "MONSTER", + "copy-from": "mon_fish_medium", + "name": { "str_sp": "atlantic mackerel" }, + "description": "An Atlantic mackerel, known for its distinctive striped pattern.", + "volume": "3000 ml", + "weight": "1600 g", + "reproduction": { "baby_egg": "egg_mackerel", "baby_count": 3, "baby_timer": 20 } + }, + { + "id": "mon_fry_mackerel", + "type": "MONSTER", + "copy-from": "mon_fry", + "upgrades": { "half_life": 14, "into": "mon_fish_mackerel" }, + "name": { "str_sp": "mackerel fry" } + }, + { + "id": "mon_fish_flounder", + "type": "MONSTER", + "copy-from": "mon_fish_medium", + "name": { "str_sp": "flounder" }, + "description": "A flatfish, the flounder, also known as a fluke, likes to stay camouflaged against the ocean floor.", + "volume": "2500 ml", + "weight": "1400 g", + "reproduction": { "baby_egg": "egg_flounder", "baby_count": 2, "baby_timer": 22 } + }, + { + "id": "mon_fry_flounder", + "type": "MONSTER", + "copy-from": "mon_fry", + "upgrades": { "half_life": 14, "into": "mon_fish_flounder" }, + "name": { "str_sp": "flounder fry" } + }, + { + "id": "mon_fish_blackfish", + "type": "MONSTER", + "copy-from": "mon_fish_small", + "name": { "str_sp": "black sea bass" }, + "description": "A small, robust fish, the black sea bass is known for its dark, mottled color and meaty texture.", + "volume": "1500 ml", + "weight": "600 g", + "reproduction": { "baby_egg": "egg_blackfish", "baby_count": 2, "baby_timer": 15 } + }, + { + "id": "mon_fry_blackfish", + "type": "MONSTER", + "copy-from": "mon_fry", + "upgrades": { "half_life": 14, "into": "mon_fish_blackfish" }, + "name": { "str_sp": "black sea bass fry" } + }, + { + "id": "mon_fish_porgy", + "type": "MONSTER", + "copy-from": "mon_fish_small", + "name": { "str_sp": "scup" }, + "description": "Also known as porgy, the scup is a small fish commonly found in Atlantic coastal waters, recognizable by its silver body with blue and purple tinges.", + "volume": "1300 ml", + "weight": "550 g", + "reproduction": { "baby_egg": "egg_porgy", "baby_count": 3, "baby_timer": 16 } + }, + { + "id": "mon_fry_porgy", + "type": "MONSTER", + "copy-from": "mon_fry", + "upgrades": { "half_life": 14, "into": "mon_fish_porgy" }, + "name": { "str_sp": "scup (porgy) fry" } + }, + { + "id": "mon_fish_bluefish", + "type": "MONSTER", + "copy-from": "mon_fish_small", + "name": { "str_sp": "bluefish" }, + "description": "The bluefish, a moderately proportioned marine fish, is known for its aggressive nature and sharp teeth. It sports a distinct blue-green coloration.", + "volume": "1600 ml", + "weight": "700 g", + "reproduction": { "baby_egg": "egg_bluefish", "baby_count": 2, "baby_timer": 18 } + }, + { + "id": "mon_fry_bluefish", + "type": "MONSTER", + "copy-from": "mon_fry", + "upgrades": { "half_life": 14, "into": "mon_fish_bluefish" }, + "name": { "str_sp": "bluefish fry" } + }, + { + "id": "mon_fish_cod", + "type": "MONSTER", + "copy-from": "mon_fish_large", + "name": { "str_sp": "Atlantic cod" }, + "description": "A large, white-meat fish known for its mild flavor and flaky texture. Highly prized in both commercial and recreational fishing.", + "volume": "35000 ml", + "weight": "22 kg", + "reproduction": { "baby_egg": "egg_cod", "baby_count": 3, "baby_timer": 19 } + }, + { + "id": "mon_fry_cod", + "type": "MONSTER", + "copy-from": "mon_fry", + "upgrades": { "half_life": 14, "into": "mon_fish_cod" }, + "name": { "str_sp": "cod fry" } + }, + { + "id": "mon_fish_haddock", + "type": "MONSTER", + "copy-from": "mon_fish_large", + "name": { "str_sp": "haddock" }, + "description": "A popular food fish, the haddock is recognized by its dark lateral line and a black blotch above the pectoral fin.", + "volume": "25500 ml", + "weight": "11 kg", + "reproduction": { "baby_egg": "egg_haddock", "baby_count": 3, "baby_timer": 18 } + }, + { + "id": "mon_fry_haddock", + "type": "MONSTER", + "copy-from": "mon_fry", + "upgrades": { "half_life": 14, "into": "mon_fish_haddock" }, + "name": { "str_sp": "haddock fry" } + }, + { + "id": "mon_fish_bluefin_tuna", + "type": "MONSTER", + "copy-from": "mon_fish_huge", + "name": { "str_sp": "Atlantic bluefin tuna" }, + "description": "One of the largest and fastest fish in the waters of New England, the bluefin tuna is a streamlined predator with a dark blue back and silvery sides.", + "volume": "125000 ml", + "weight": "98 kg", + "reproduction": { "baby_egg": "egg_bluefin_tuna", "baby_count": 1, "baby_timer": 22 } + }, + { + "id": "mon_fry_bluefin_tuna", + "type": "MONSTER", + "copy-from": "mon_fry", + "upgrades": { "half_life": 14, "into": "mon_fish_bluefin_tuna" }, + "name": { "str_sp": "bluefin tuna fry" } + }, + { + "id": "mon_fish_halibut", + "type": "MONSTER", + "copy-from": "mon_fish_huge", + "name": { "str_sp": "Atlantic halibut" }, + "description": "The largest flatfish in the ocean, known for its dense, firm texture and mild flavor.", + "volume": "75000 ml", + "weight": "42 kg", + "reproduction": { "baby_egg": "egg_halibut", "baby_count": 2, "baby_timer": 20 } + }, + { + "id": "mon_fry_halibut", + "type": "MONSTER", + "copy-from": "mon_fry", + "upgrades": { "half_life": 14, "into": "mon_fish_halibut" }, + "name": { "str_sp": "halibut fry" } + }, + { + "id": "mon_fish_pollock", + "type": "MONSTER", + "copy-from": "mon_fish_large", + "name": { "str_sp": "pollock" }, + "looks_like": "mon_fish_cod", + "description": "A member of the cod family, pollock is a versatile fish known for its white, delicate meat and mild taste.", + "volume": "28000 ml", + "weight": "17 kg", + "reproduction": { "baby_egg": "egg_pollock", "baby_count": 3, "baby_timer": 17 } + }, + { + "id": "mon_fry_pollock", + "type": "MONSTER", + "copy-from": "mon_fry", + "upgrades": { "half_life": 14, "into": "mon_fish_pollock" }, + "name": { "str_sp": "pollock fry" } } ] diff --git a/data/json/monsters/zed-animal.json b/data/json/monsters/zed-animal.json index 04799ec654015..04d13a7a99923 100644 --- a/data/json/monsters/zed-animal.json +++ b/data/json/monsters/zed-animal.json @@ -41,6 +41,48 @@ ], "armor": { "bash": 6, "cut": 2, "bullet": 2 } }, + { + "id": "mon_ocean_zhark", + "type": "MONSTER", + "name": { "str": "abyssal terror" }, + "description": "Once a former apex predator of the seas, now an undead nightmare, this zombified Great White shark terrorizes the waters with its relentless hunger and aggression.", + "default_faction": "zombie_aquatic", + "bodytype": "fish", + "species": [ "ZOMBIE" ], + "volume": "200000 ml", + "weight": "350 kg", + "hp": 600, + "speed": 175, + "attack_cost": 200, + "material": [ "flesh" ], + "symbol": "^", + "color": "white_magenta", + "scents_tracked": [ "sc_human", "sc_fetid" ], + "aggression": 100, + "morale": 105, + "melee_skill": 8, + "melee_dice": 4, + "melee_dice_sides": 6, + "melee_damage": [ { "damage_type": "cut", "amount": 12 } ], + "dodge": 3, + "luminance": 0, + "families": [ "prof_intro_biology", "prof_physiology", "prof_wp_zombie" ], + "harvest": "zombie_leather", + "flags": [ + "SEES", + "HEARS", + "SMELLS", + "WARM", + "SWIMS", + "AQUATIC", + "POISON", + "NO_BREATHE", + "REVIVES", + "FILTHY", + "WATER_CAMOUFLAGE" + ], + "armor": { "bash": 8, "cut": 2, "bullet": 2 } + }, { "id": "mon_zombie_dog", "alias": "mon_zombie_fast", diff --git a/data/json/requirements/cooking_components.json b/data/json/requirements/cooking_components.json index b9d5ad00c5c91..f3514f5d4f4fc 100644 --- a/data/json/requirements/cooking_components.json +++ b/data/json/requirements/cooking_components.json @@ -234,7 +234,17 @@ [ "egg_burbot", 1 ], [ "egg_sturgeon_lake", 1 ], [ "egg_sturgeon_shortnose", 1 ], - [ "egg_fallfish", 1 ] + [ "egg_fallfish", 1 ], + [ "egg_cod", 1 ], + [ "egg_haddock", 1 ], + [ "egg_bluefin_tuna", 1 ], + [ "egg_halibut", 1 ], + [ "egg_pollock", 1 ], + [ "egg_flounder", 1 ], + [ "egg_mackerel", 1 ], + [ "egg_bluefish", 1 ], + [ "egg_blackfish", 1 ], + [ "egg_porgy", 1 ] ] ] }, diff --git a/src/overmap.cpp b/src/overmap.cpp index f2f2bd53501ca..26cdd828f8c8c 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -61,6 +61,8 @@ #include "translations.h" static const mongroup_id GROUP_NEMESIS( "GROUP_NEMESIS" ); +static const mongroup_id GROUP_OCEAN_DEEP( "GROUP_OCEAN_DEEP" ); +static const mongroup_id GROUP_OCEAN_SHORE( "GROUP_OCEAN_SHORE" ); static const mongroup_id GROUP_RIVER( "GROUP_RIVER" ); static const mongroup_id GROUP_SUBWAY_CITY( "GROUP_SUBWAY_CITY" ); static const mongroup_id GROUP_SWAMP( "GROUP_SWAMP" ); @@ -592,6 +594,11 @@ bool is_water_body( const oter_id &ter ) ter->is_ocean_shore(); } +bool is_ocean( const oter_id &ter ) +{ + return ter->is_ocean() || ter->is_ocean_shore(); +} + bool is_ot_match( const std::string &name, const oter_id &oter, const ot_match_type match_type ) { @@ -4688,6 +4695,36 @@ void overmap::place_lakes() } } +// helper function for code deduplication, as it is needed multiple times +float overmap::calculate_ocean_gradient( const point_om_omt &p, const point_abs_om this_om ) +{ + const int northern_ocean = settings->overmap_ocean.ocean_start_north; + const int eastern_ocean = settings->overmap_ocean.ocean_start_east; + const int western_ocean = settings->overmap_ocean.ocean_start_west; + const int southern_ocean = settings->overmap_ocean.ocean_start_south; + + float ocean_adjust_N = 0.0f; + float ocean_adjust_E = 0.0f; + float ocean_adjust_W = 0.0f; + float ocean_adjust_S = 0.0f; + if( northern_ocean > 0 && this_om.y() <= northern_ocean * -1 ) { + ocean_adjust_N = 0.0005f * static_cast( OMAPY - p.y() + + std::abs( ( this_om.y() + northern_ocean ) * OMAPY ) ); + } + if( eastern_ocean > 0 && this_om.x() >= eastern_ocean ) { + ocean_adjust_E = 0.0005f * static_cast( p.x() + ( this_om.x() - eastern_ocean ) + * OMAPX ); + } + if( western_ocean > 0 && this_om.x() <= western_ocean * -1 ) { + ocean_adjust_W = 0.0005f * static_cast( OMAPX - p.x() + + std::abs( ( this_om.x() + western_ocean ) * OMAPX ) ); + } + if( southern_ocean > 0 && this_om.y() >= southern_ocean ) { + ocean_adjust_S = 0.0005f * static_cast( p.y() + ( this_om.y() - southern_ocean ) * OMAPY ); + } + return std::max( { ocean_adjust_N, ocean_adjust_E, ocean_adjust_W, ocean_adjust_S } ); +} + void overmap::place_oceans() { int northern_ocean = settings->overmap_ocean.ocean_start_north; @@ -4698,30 +4735,6 @@ void overmap::place_oceans() const om_noise::om_noise_layer_ocean f( global_base_point(), g->get_seed() ); const point_abs_om this_om = pos(); - // This is my first lambda, be nice to me. - const auto calculate_ocean_gradient = [&]( const point_om_omt & p ) { - float ocean_adjust_N = 0.0f; - float ocean_adjust_E = 0.0f; - float ocean_adjust_W = 0.0f; - float ocean_adjust_S = 0.0f; - if( northern_ocean > 0 && this_om.y() <= northern_ocean * -1 ) { - ocean_adjust_N = 0.0005f * static_cast( OMAPY - p.y() - + std::abs( ( this_om.y() + northern_ocean ) * OMAPY ) ); - } - if( eastern_ocean > 0 && this_om.x() >= eastern_ocean ) { - ocean_adjust_E = 0.0005f * static_cast( p.x() + ( this_om.x() - eastern_ocean ) - * OMAPX ); - } - if( western_ocean > 0 && this_om.x() <= western_ocean * -1 ) { - ocean_adjust_W = 0.0005f * static_cast( OMAPX - p.x() - + std::abs( ( this_om.x() + western_ocean ) * OMAPX ) ); - } - if( southern_ocean > 0 && this_om.y() >= southern_ocean ) { - ocean_adjust_S = 0.0005f * static_cast( p.y() + ( this_om.y() - southern_ocean ) * OMAPY ); - } - return std::max( {ocean_adjust_N, ocean_adjust_E, ocean_adjust_W, ocean_adjust_S} ); - }; - const auto is_ocean = [&]( const point_om_omt & p ) { // credit to ehughsbaird for thinking up this inbounds solution to infinite flood fill lag. if( northern_ocean == 0 && eastern_ocean == 0 && western_ocean == 0 && southern_ocean == 0 ) { @@ -4732,7 +4745,7 @@ void overmap::place_oceans() if( !inbounds ) { return false; } - float ocean_adjust = calculate_ocean_gradient( p ); + float ocean_adjust = calculate_ocean_gradient( p, this_om ); if( ocean_adjust == 0.0f ) { // It's too soon! Too soon for an ocean!! ABORT!!! return false; @@ -7009,14 +7022,80 @@ void overmap::place_mongroups() } } + // Now place ocean mongroup. Weights may need to be altered. + const om_noise::om_noise_layer_ocean f( global_base_point(), g->get_seed() ); + const point_abs_om this_om = pos(); + const int northern_ocean = settings->overmap_ocean.ocean_start_north; + const int eastern_ocean = settings->overmap_ocean.ocean_start_east; + const int western_ocean = settings->overmap_ocean.ocean_start_west; + const int southern_ocean = settings->overmap_ocean.ocean_start_south; + + // noise threshold adjuster for deep ocean. Increase to make deep ocean move further from the shore. + constexpr float DEEP_OCEAN_THRESHOLD_ADJUST = 1.25; + + // code taken from place_oceans, but noise threshold increased to determine "deep ocean". + const auto is_deep_ocean = [&]( const point_om_omt & p ) { + // credit to ehughsbaird for thinking up this inbounds solution to infinite flood fill lag. + if( northern_ocean == 0 && eastern_ocean == 0 && western_ocean == 0 && southern_ocean == 0 ) { + // you know you could just turn oceans off in global_settings.json right? + return false; + } + bool inbounds = p.x() > -5 && p.y() > -5 && p.x() < OMAPX + 5 && p.y() < OMAPY + 5; + if( !inbounds ) { + return false; + } + float ocean_adjust = calculate_ocean_gradient( p, this_om ); + if( ocean_adjust == 0.0f ) { + // It's too soon! Too soon for an ocean!! ABORT!!! + return false; + } + return f.noise_at( p ) + ocean_adjust > settings->overmap_ocean.noise_threshold_ocean * + DEEP_OCEAN_THRESHOLD_ADJUST; + }; + + for( int x = 3; x < OMAPX - 3; x += 7 ) { + for( int y = 3; y < OMAPY - 3; y += 7 ) { + int ocean_count = 0; + for( int sx = x - 3; sx <= x + 3; sx++ ) { + for( int sy = y - 3; sy <= y + 3; sy++ ) { + if( is_ocean( ter( { sx, sy, 0 } ) ) ) { + ocean_count++; + } + } + } + bool am_deep = is_deep_ocean( { x, y } ); + if( ocean_count >= 25 ) { + tripoint_om_omt p( x, y, 0 ); + if( am_deep ) { + float norm_factor = std::abs( GROUP_OCEAN_DEEP->freq_total / 1000.0f ); + unsigned int pop = + std::round( norm_factor * rng( ocean_count * 8, ocean_count * 25 ) ); + spawn_mon_group( + mongroup( GROUP_OCEAN_DEEP, project_combine( pos(), project_to( p ) ), + pop ), 3 ); + } else { + float norm_factor = std::abs( GROUP_OCEAN_SHORE->freq_total / 1000.0f ); + unsigned int pop = + std::round( norm_factor * rng( ocean_count * 8, ocean_count * 25 ) ); + spawn_mon_group( + mongroup( GROUP_OCEAN_SHORE, project_combine( pos(), project_to( p ) ), + pop ), 3 ); + } + } + } + } + // Place the "put me anywhere" groups int numgroups = rng( 0, 3 ); for( int i = 0; i < numgroups; i++ ) { float norm_factor = std::abs( GROUP_WORM->freq_total / 1000.0f ); tripoint_om_sm p( rng( 0, OMAPX * 2 - 1 ), rng( 0, OMAPY * 2 - 1 ), 0 ); unsigned int pop = std::round( norm_factor * rng( 30, 50 ) ); - spawn_mon_group( - mongroup( GROUP_WORM, project_combine( pos(), p ), pop ), rng( 20, 40 ) ); + // ensure GROUP WORM doesn't get placed in ocean or lake. + if( !is_water_body( ter( {p.x(), p.y(), 0} ) ) ) { + spawn_mon_group( + mongroup( GROUP_WORM, project_combine( pos(), p ), pop ), rng( 20, 40 ) ); + } } } diff --git a/src/overmap.h b/src/overmap.h index 8f93d36b35056..659a5b2ed0ac9 100644 --- a/src/overmap.h +++ b/src/overmap.h @@ -426,6 +426,8 @@ class overmap void place_nemesis( const tripoint_abs_omt & ); bool remove_nemesis(); // returns true if nemesis found and removed + // code deduplication - calc ocean gradient + float calculate_ocean_gradient( const point_om_omt &p, point_abs_om this_omt ); // Overall terrain void place_river( const point_om_omt &pa, const point_om_omt &pb ); void place_forests(); @@ -555,6 +557,7 @@ class overmap bool is_river( const oter_id &ter ); bool is_water_body( const oter_id &ter ); bool is_lake_or_river( const oter_id &ter ); +bool is_ocean( const oter_id &ter ); /** * Determine if the provided name is a match with the provided overmap terrain