mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-09 23:27:56 +01:00
439 lines
18 KiB
Plaintext
439 lines
18 KiB
Plaintext
/// The random offset applied to square coordinates, causes intermingling at biome borders
|
|
#define BIOME_RANDOM_SQUARE_DRIFT 2
|
|
// Categories for spawned things
|
|
#define CAVE_SPAWN_MOB "mob"
|
|
#define CAVE_SPAWN_FEATURE "feature"
|
|
#define CAVE_SPAWN_TENDRIL "tendril"
|
|
#define CAVE_SPAWN_MEGAFAUNA "megafauna"
|
|
|
|
/datum/map_generator/cave_generator
|
|
var/name = "Cave Generator"
|
|
///Weighted list of the types that spawns if the turf is open
|
|
var/weighted_open_turf_types = list(/turf/open/misc/asteroid/airless = 1)
|
|
///Expanded list of the types that spawns if the turf is open
|
|
var/open_turf_types
|
|
///Weighted list of the types that spawns if the turf is closed
|
|
var/weighted_closed_turf_types = list(/turf/closed/mineral/random = 1)
|
|
///Expanded list of the types that spawns if the turf is closed
|
|
var/closed_turf_types
|
|
|
|
|
|
///Weighted list of mobs that can spawn in the area.
|
|
var/list/weighted_mob_spawn_list
|
|
///Expanded list of mobs that can spawn in the area. Reads from the weighted list
|
|
var/list/mob_spawn_list
|
|
///The mob spawn list but with no megafauna markers. autogenerated
|
|
var/list/mob_spawn_no_mega_list
|
|
// Weighted list of Megafauna that can spawn in the area
|
|
var/list/weighted_megafauna_spawn_list
|
|
///Expanded list of Megafauna that can spawn in the area. Reads from the weighted list
|
|
var/list/megafauna_spawn_list
|
|
///Weighted list of flora that can spawn in the area.
|
|
var/list/weighted_flora_spawn_list
|
|
///Expanded list of flora that can spawn in the area. Reads from the weighted list
|
|
var/list/flora_spawn_list
|
|
///Weighted list of extra features that can spawn in the area, such as geysers.
|
|
var/list/weighted_feature_spawn_list
|
|
///Expanded list of extra features that can spawn in the area. Reads from the weighted list
|
|
var/list/feature_spawn_list
|
|
/// An associative list of biome type to the list of turfs that were
|
|
/// generated of that biome specifically. Helps to improve the efficiency
|
|
/// of biome-related operations. Is populated through
|
|
/// `generate_terrain_with_biomes()`.
|
|
var/list/generated_turfs_per_biome = list()
|
|
/// Same as generated_turfs_per_biome, but additionally indexed by area
|
|
var/list/generated_turfs_per_area_biome = list()
|
|
/// 2D list of all biomes based on heat and humidity combos. Associative by
|
|
/// `BIOME_X_HEAT` and then by `BIOME_X_HUMIDITY` (i.e.
|
|
/// `possible_biomes[BIOME_LOW_HEAT][BIOME_LOWMEDIUM_HUMIDITY]`).
|
|
/// Check /datum/map_generator/cave_generator/jungle for an example
|
|
/// of how to set it up properly.
|
|
var/list/possible_biomes = list()
|
|
/// Used to select "zoom" level into the perlin noise, higher numbers
|
|
/// result in slower transitions
|
|
var/perlin_zoom = 65
|
|
|
|
/// Should we populate turfs through biome datums if we have such
|
|
var/biome_population = TRUE
|
|
/// Noise threshold above which a biome is considered high heat
|
|
var/high_heat_threshold = -0.1
|
|
/// Noise threshold above which a biome is considered medium heat
|
|
var/medium_heat_threshold = -0.3
|
|
/// Noise threshold above which a biome is considered high humidity
|
|
var/high_humidity_threshold = -0.1
|
|
/// Noise threshold above which a biome is considered medium humidity
|
|
var/medium_humidity_threshold = -0.3
|
|
/// Should all generators on the same z level use the same seeds?
|
|
var/shared_seed = TRUE
|
|
/// Stamp size for DBP noise, aka frequency
|
|
var/biome_stamp_size = 75
|
|
/// Stored noise maps per z level if we use a shared seed
|
|
var/static_biome_maps = list()
|
|
|
|
/// Base chance of spawning a mob
|
|
var/mob_spawn_chance = 6
|
|
/// Base chance of spawning flora
|
|
var/flora_spawn_chance = 2
|
|
/// Base chance of spawning features
|
|
var/feature_spawn_chance = 0.25
|
|
/// Unique ID for this spawner
|
|
var/string_gen
|
|
|
|
/// Radius around features within which we avoid spawning other features
|
|
var/feature_exclusion_radius = 7
|
|
/// Radius around mobs which we avoid spawning other mobs
|
|
var/mob_exclusion_radius = 12
|
|
/// Radius around megafauna within which we avoid spawning tendrils
|
|
var/megafauna_exclusion_radius = 7
|
|
|
|
///Chance of cells starting closed
|
|
var/initial_closed_chance = 45
|
|
///Amount of smoothing iterations
|
|
var/smoothing_iterations = 20
|
|
///How much neighbours does a dead cell need to become alive
|
|
var/birth_limit = 4
|
|
///How little neighbours does a alive cell need to die
|
|
var/death_limit = 3
|
|
|
|
|
|
/datum/map_generator/cave_generator/New()
|
|
. = ..()
|
|
if(!weighted_mob_spawn_list)
|
|
weighted_mob_spawn_list = list(
|
|
/mob/living/basic/mining/basilisk = 4,
|
|
/mob/living/basic/mining/goldgrub = 1,
|
|
/mob/living/basic/mining/goliath/ancient = 5,
|
|
/mob/living/basic/mining/hivelord = 3,
|
|
)
|
|
mob_spawn_list = expand_weights(weighted_mob_spawn_list)
|
|
mob_spawn_no_mega_list = expand_weights(weighted_mob_spawn_list - SPAWN_MEGAFAUNA)
|
|
if(!weighted_megafauna_spawn_list)
|
|
weighted_megafauna_spawn_list = GLOB.megafauna_spawn_list
|
|
megafauna_spawn_list = expand_weights(weighted_megafauna_spawn_list)
|
|
if(!weighted_flora_spawn_list)
|
|
weighted_flora_spawn_list = list(
|
|
/obj/structure/flora/ash/leaf_shroom = 2,
|
|
/obj/structure/flora/ash/cap_shroom = 2,
|
|
/obj/structure/flora/ash/stem_shroom = 2,
|
|
/obj/structure/flora/ash/cacti = 1,
|
|
/obj/structure/flora/ash/tall_shroom = 2,
|
|
/obj/structure/flora/ash/seraka = 2,
|
|
)
|
|
flora_spawn_list = expand_weights(weighted_flora_spawn_list)
|
|
if(!weighted_feature_spawn_list)
|
|
weighted_feature_spawn_list = list(
|
|
/obj/structure/geyser/random = 1,
|
|
/obj/structure/ore_vent/random = 1,
|
|
)
|
|
feature_spawn_list = expand_weights(weighted_feature_spawn_list)
|
|
open_turf_types = expand_weights(weighted_open_turf_types)
|
|
closed_turf_types = expand_weights(weighted_closed_turf_types)
|
|
|
|
/datum/map_generator/cave_generator/generate_terrain(list/turfs, area/generate_in)
|
|
. = ..()
|
|
if(!(generate_in.area_flags_mapping & CAVES_ALLOWED))
|
|
return
|
|
|
|
if(length(possible_biomes))
|
|
return generate_terrain_with_biomes(turfs, generate_in)
|
|
|
|
var/start_time = REALTIMEOFDAY
|
|
string_gen = rustg_cnoise_generate("[initial_closed_chance]", "[smoothing_iterations]", "[birth_limit]", "[death_limit]", "[world.maxx]", "[world.maxy]") //Generate the raw CA data
|
|
|
|
for(var/turf/gen_turf as anything in turfs) //Go through all the turfs and generate them
|
|
//SKYRAT EDIT ADDITION
|
|
if(istype(gen_turf, /turf/open/space/mirage))
|
|
continue
|
|
//SKYRAT EDIT END
|
|
|
|
var/closed = string_gen[world.maxx * (gen_turf.y - 1) + gen_turf.x] != "0"
|
|
var/turf/new_turf = pick(closed ? closed_turf_types : open_turf_types)
|
|
|
|
// The assumption is this will be faster then changeturf, and changeturf isn't required since by this point
|
|
// The old tile hasn't got the chance to init yet
|
|
new_turf = new new_turf(gen_turf)
|
|
|
|
if(gen_turf.turf_flags & NO_RUINS)
|
|
new_turf.turf_flags |= NO_RUINS
|
|
|
|
var/message = "[name] terrain generation finished in [(REALTIMEOFDAY - start_time)/10]s!"
|
|
to_chat(world, span_boldannounce("[message]"), MESSAGE_TYPE_DEBUG)
|
|
log_world(message)
|
|
|
|
|
|
/**
|
|
* This proc handles including biomes in the cave generation. This is slower than
|
|
* `generate_terrain()`, so please use it only if you actually need biomes.
|
|
*
|
|
* This should only be called by `generate_terrain()`, if you have to call this,
|
|
* you're probably doing something wrong.
|
|
*/
|
|
/datum/map_generator/cave_generator/proc/generate_terrain_with_biomes(list/turf/turfs, area/generate_in)
|
|
if(!(generate_in.area_flags_mapping & CAVES_ALLOWED))
|
|
return
|
|
|
|
var/humidity_seed = null
|
|
var/heat_seed = null
|
|
|
|
// Make sure that all caves on the same z level generate smoothly regardless of the area
|
|
if (shared_seed)
|
|
var/static/list/static_heat = null
|
|
var/static/list/static_humi = null
|
|
if (!static_heat)
|
|
static_heat = list()
|
|
static_humi = list()
|
|
|
|
var/z_key = "[turfs[1].z]"
|
|
if (!static_heat[z_key])
|
|
static_heat[z_key] = rand(0, 50000)
|
|
static_humi[z_key] = rand(0, 50000)
|
|
|
|
heat_seed = static_heat[z_key]
|
|
humidity_seed = static_humi[z_key]
|
|
else
|
|
humidity_seed = rand(0, 50000)
|
|
heat_seed = rand(0, 50000)
|
|
|
|
var/start_time = REALTIMEOFDAY
|
|
string_gen = rustg_cnoise_generate("[initial_closed_chance]", "[smoothing_iterations]", "[birth_limit]", "[death_limit]", "[world.maxx]", "[world.maxy]") //Generate the raw CA data
|
|
|
|
var/humidity_gen = list()
|
|
humidity_gen[BIOME_HIGH_HUMIDITY] = rustg_dbp_generate("[humidity_seed]", "60", "[biome_stamp_size]", "[world.maxx]", "[high_heat_threshold]", "1.1")
|
|
humidity_gen[BIOME_MEDIUM_HUMIDITY] = rustg_dbp_generate("[humidity_seed]", "60", "[biome_stamp_size]", "[world.maxx]", "[medium_heat_threshold]", "[high_heat_threshold]")
|
|
|
|
var/heat_gen = list()
|
|
heat_gen[BIOME_HIGH_HEAT] = rustg_dbp_generate("[heat_seed]", "60", "[biome_stamp_size]", "[world.maxx]", "[high_heat_threshold]", "1.1")
|
|
heat_gen[BIOME_MEDIUM_HEAT] = rustg_dbp_generate("[heat_seed]", "60", "[biome_stamp_size]", "[world.maxx]", "[medium_heat_threshold]", "[high_heat_threshold]")
|
|
|
|
if (shared_seed)
|
|
static_biome_maps["[turfs[1].z]"] = list(
|
|
BIOME_HIGH_HUMIDITY = humidity_gen[BIOME_HIGH_HUMIDITY],
|
|
BIOME_MEDIUM_HUMIDITY = humidity_gen[BIOME_MEDIUM_HUMIDITY],
|
|
BIOME_HIGH_HEAT = heat_gen[BIOME_HIGH_HEAT],
|
|
BIOME_MEDIUM_HEAT = heat_gen[BIOME_MEDIUM_HEAT],
|
|
)
|
|
|
|
var/list/to_generate = list()
|
|
for(var/turf/gen_turf as anything in turfs) //Go through all the turfs and generate them
|
|
var/closed = string_gen[world.maxx * (gen_turf.y - 1) + gen_turf.x] != "0"
|
|
var/datum/biome/selected_biome
|
|
|
|
// Here comes the meat of the biome code.
|
|
var/drift_x = clamp((gen_turf.x + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)), 1, world.maxx) // / perlin_zoom
|
|
var/drift_y = clamp((gen_turf.y + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)), 2, world.maxy) // / perlin_zoom
|
|
|
|
// Where we go in the generated string (generated outside of the loop for s p e e d)
|
|
var/coordinate = world.maxx * (drift_y - 1) + drift_x
|
|
|
|
// Type of humidity zone we're in (LOW-MEDIUM-HIGH)
|
|
var/humidity_level = text2num(humidity_gen[BIOME_HIGH_HUMIDITY][coordinate]) ? \
|
|
BIOME_HIGH_HUMIDITY : text2num(humidity_gen[BIOME_MEDIUM_HUMIDITY][coordinate]) ? BIOME_MEDIUM_HUMIDITY : BIOME_LOW_HUMIDITY
|
|
// Type of heat zone we're in (LOW-MEDIUM-HIGH)
|
|
var/heat_level = text2num(heat_gen[BIOME_HIGH_HEAT][coordinate]) ? \
|
|
BIOME_HIGH_HEAT : text2num(heat_gen[BIOME_MEDIUM_HEAT][coordinate]) ? BIOME_MEDIUM_HEAT : BIOME_LOW_HEAT
|
|
|
|
selected_biome = possible_biomes[heat_level][humidity_level]
|
|
LAZYSET(to_generate[selected_biome], gen_turf, closed)
|
|
CHECK_TICK
|
|
|
|
for(var/biome in to_generate)
|
|
var/datum/biome/generating_biome = SSmapping.biomes[biome]
|
|
var/list/turf/generated_turfs = generating_biome.generate_turfs_for_terrain(to_generate[biome])
|
|
generated_turfs_per_biome[biome] = (generated_turfs_per_biome[biome] || list()) + generated_turfs
|
|
var/list/area_list = generated_turfs_per_area_biome[biome]
|
|
if (!area_list)
|
|
area_list = list()
|
|
generated_turfs_per_area_biome[biome] = area_list
|
|
area_list[generate_in] = generated_turfs
|
|
|
|
var/message = "[name] terrain generation finished in [(REALTIMEOFDAY - start_time)/10]s!"
|
|
to_chat(world, span_boldannounce("[message]"), MESSAGE_TYPE_DEBUG)
|
|
log_world(message)
|
|
|
|
/// Returns a biome datum that the turf was initialized with, or would be if it is present on our Z level and we use a consistent shared seed
|
|
/// Not consistent between calls by itself due to using RNG in perlin zoom, needs a static coordinate-based formula
|
|
/datum/map_generator/cave_generator/proc/get_biome_for_turf(turf/target)
|
|
for (var/biome in generated_turfs_per_biome)
|
|
var/list/generated_turfs = generated_turfs_per_biome[biome]
|
|
if (generated_turfs[target])
|
|
return biome
|
|
|
|
var/list/biome_map = static_biome_maps["[target.z]"]
|
|
if (!shared_seed || !biome_map)
|
|
return null
|
|
|
|
var/drift_x = clamp((target.x + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)), 1, world.maxx)
|
|
var/drift_y = clamp((target.y + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)), 2, world.maxy)
|
|
var/coordinate = world.maxx * (drift_y - 1) + drift_x
|
|
|
|
var/humidity_level = text2num(biome_map[BIOME_HIGH_HUMIDITY][coordinate]) ? \
|
|
BIOME_HIGH_HUMIDITY : text2num(biome_map[BIOME_MEDIUM_HUMIDITY][coordinate]) ? BIOME_MEDIUM_HUMIDITY : BIOME_LOW_HUMIDITY
|
|
var/heat_level = text2num(biome_map[BIOME_HIGH_HEAT][coordinate]) ? \
|
|
BIOME_HIGH_HEAT : text2num(biome_map[BIOME_MEDIUM_HEAT][coordinate]) ? BIOME_MEDIUM_HEAT : BIOME_LOW_HEAT
|
|
|
|
return possible_biomes[heat_level][humidity_level]
|
|
|
|
/datum/map_generator/cave_generator/populate_terrain(list/turfs, area/generate_in)
|
|
if (biome_population && length(possible_biomes))
|
|
return populate_terrain_with_biomes(turfs, generate_in)
|
|
|
|
// Area var pullouts to make accessing in the loop faster
|
|
var/flora_allowed = (generate_in.area_flags_mapping & FLORA_ALLOWED) && length(flora_spawn_list)
|
|
var/feature_allowed = (generate_in.area_flags_mapping & FLORA_ALLOWED) && length(feature_spawn_list)
|
|
var/mobs_allowed = (generate_in.area_flags_mapping & MOB_SPAWN_ALLOWED) && length(mob_spawn_list)
|
|
var/megas_allowed = (generate_in.area_flags_mapping & MEGAFAUNA_SPAWN_ALLOWED) && length(megafauna_spawn_list)
|
|
|
|
var/start_time = REALTIMEOFDAY
|
|
|
|
// Assoc list of spawned categories to
|
|
var/list/spawn_data = list(
|
|
CAVE_SPAWN_FEATURE = list(),
|
|
CAVE_SPAWN_TENDRIL = list(),
|
|
CAVE_SPAWN_MOB = list(),
|
|
CAVE_SPAWN_MEGAFAUNA = list(),
|
|
)
|
|
|
|
var/list/open_turf_cache = typecacheof(open_turf_types)
|
|
for (var/turf/target_turf as anything in turfs)
|
|
// Only put stuff on open turfs we generated, so closed walls and rivers and stuff are skipped
|
|
if (!is_type_in_typecache(target_turf, open_turf_cache))
|
|
continue
|
|
|
|
CHECK_TICK
|
|
|
|
if (!(target_turf.turf_flags & TURF_BLOCKS_POPULATE_TERRAIN_FLORAFEATURES))
|
|
if (flora_allowed && prob(flora_spawn_chance))
|
|
var/flora_type = pick(flora_spawn_list)
|
|
new flora_type(target_turf)
|
|
continue
|
|
|
|
if (feature_allowed && prob(feature_spawn_chance))
|
|
var/can_spawn = TRUE
|
|
for(var/turf/spawn_turf as anything in spawn_data[CAVE_SPAWN_FEATURE])
|
|
if (get_dist(spawn_turf, target_turf) <= feature_exclusion_radius)
|
|
can_spawn = FALSE
|
|
break
|
|
|
|
if (can_spawn)
|
|
var/picked_feature = pick(feature_spawn_list)
|
|
new picked_feature(target_turf)
|
|
spawn_data[CAVE_SPAWN_FEATURE] += target_turf
|
|
continue
|
|
|
|
if (!mobs_allowed || !prob(mob_spawn_chance))
|
|
continue
|
|
|
|
var/picked_mob = pick(megas_allowed ? mob_spawn_list : mob_spawn_no_mega_list)
|
|
var/is_megafauna = FALSE
|
|
if (picked_mob == SPAWN_MEGAFAUNA)
|
|
picked_mob = pick(megafauna_spawn_list)
|
|
is_megafauna = TRUE
|
|
|
|
var/can_spawn = TRUE
|
|
if(ispath(picked_mob, /mob/living/basic/mining/tendril))
|
|
// Prevents tendrils spawning in each other's collapse range
|
|
for(var/turf/spawn_turf as anything in spawn_data[CAVE_SPAWN_TENDRIL])
|
|
if (get_dist(spawn_turf, target_turf) <= 2)
|
|
can_spawn = FALSE
|
|
break
|
|
|
|
// Also avoid spawning them next to megafauna
|
|
for(var/turf/spawn_turf as anything in spawn_data[CAVE_SPAWN_MEGAFAUNA])
|
|
if (get_dist(spawn_turf, target_turf) <= megafauna_exclusion_radius)
|
|
can_spawn = FALSE
|
|
break
|
|
else if (is_megafauna)
|
|
// Megafauna can spawn wherever it wants as long as its not next to another mega
|
|
for(var/turf/spawn_turf as anything in spawn_data[CAVE_SPAWN_MEGAFAUNA])
|
|
if (get_dist(spawn_turf, target_turf) <= megafauna_exclusion_radius)
|
|
can_spawn = FALSE
|
|
break
|
|
else
|
|
for(var/turf/spawn_turf as anything in spawn_data[CAVE_SPAWN_MOB])
|
|
if (get_dist(spawn_turf, target_turf) <= mob_exclusion_radius)
|
|
can_spawn = FALSE
|
|
break
|
|
|
|
if (!can_spawn)
|
|
continue
|
|
|
|
if (ispath(picked_mob, /mob/living/basic/mining/tendril))
|
|
spawn_data[CAVE_SPAWN_TENDRIL] += target_turf
|
|
else
|
|
if (is_megafauna)
|
|
spawn_data[CAVE_SPAWN_MEGAFAUNA] += target_turf
|
|
spawn_data[CAVE_SPAWN_MOB] += target_turf
|
|
|
|
new picked_mob(target_turf)
|
|
|
|
// There can be only one Bubblegum, so don't waste spawns on it
|
|
if(ispath(picked_mob, /mob/living/simple_animal/hostile/megafauna/bubblegum))
|
|
weighted_megafauna_spawn_list.Remove(picked_mob)
|
|
megafauna_spawn_list = expand_weights(weighted_megafauna_spawn_list)
|
|
megas_allowed = megas_allowed && length(megafauna_spawn_list)
|
|
|
|
var/message = "[name] terrain population finished in [(REALTIMEOFDAY - start_time)/10]s!"
|
|
add_startup_message(message) //SKYRAT EDIT CHANGE
|
|
//to_chat(world, span_boldannounce("[message]"), MESSAGE_TYPE_DEBUG) //SKYRAT EDIT ORIGINAL
|
|
log_world(message)
|
|
|
|
/**
|
|
* This handles the population of terrain with biomes. Should only be called by
|
|
* `populate_terrain()`, if you find yourself calling this, you're probably not
|
|
* doing it right.
|
|
*
|
|
* This proc won't do anything if the area we're trying to generate in does not
|
|
* have `FLORA_ALLOWED` or `MOB_SPAWN_ALLOWED` in its `area_flags`.
|
|
*/
|
|
/datum/map_generator/cave_generator/proc/populate_terrain_with_biomes(list/turfs, area/generate_in)
|
|
// Area var pullouts to make accessing in the loop faster
|
|
var/flora_allowed = (generate_in.area_flags_mapping & FLORA_ALLOWED)
|
|
var/features_allowed = (generate_in.area_flags_mapping & FLORA_ALLOWED)
|
|
var/fauna_allowed = (generate_in.area_flags_mapping & MOB_SPAWN_ALLOWED)
|
|
|
|
var/start_time = REALTIMEOFDAY
|
|
|
|
// No sense in doing anything here if nothing is allowed anyway.
|
|
if(!flora_allowed && !features_allowed && !fauna_allowed)
|
|
var/message = "[name] terrain population finished in [(REALTIMEOFDAY - start_time)/10]s!"
|
|
to_chat(world, span_boldannounce("[message]"), MESSAGE_TYPE_DEBUG)
|
|
log_world(message)
|
|
return
|
|
|
|
for(var/biome in generated_turfs_per_area_biome)
|
|
var/datum/biome/generating_biome = SSmapping.biomes[biome]
|
|
var/list/areas_list = generated_turfs_per_area_biome[biome]
|
|
generating_biome.populate_turfs(areas_list[generate_in], flora_allowed, features_allowed, fauna_allowed)
|
|
|
|
CHECK_TICK
|
|
|
|
var/message = "[name] terrain population finished in [(REALTIMEOFDAY - start_time)/10]s!"
|
|
to_chat(world, span_boldannounce("[message]"), MESSAGE_TYPE_DEBUG)
|
|
log_world(message)
|
|
|
|
/datum/map_generator/cave_generator/jungle
|
|
possible_biomes = list(
|
|
BIOME_LOW_HEAT = list(
|
|
BIOME_LOW_HUMIDITY = /datum/biome/plains,
|
|
BIOME_MEDIUM_HUMIDITY = /datum/biome/mudlands,
|
|
BIOME_HIGH_HUMIDITY = /datum/biome/water
|
|
),
|
|
BIOME_MEDIUM_HEAT = list(
|
|
BIOME_LOW_HUMIDITY = /datum/biome/plains,
|
|
BIOME_MEDIUM_HUMIDITY = /datum/biome/jungle/deep,
|
|
BIOME_HIGH_HUMIDITY = /datum/biome/jungle
|
|
),
|
|
BIOME_HIGH_HEAT = list(
|
|
BIOME_LOW_HUMIDITY = /datum/biome/wasteland,
|
|
BIOME_MEDIUM_HUMIDITY = /datum/biome/plains,
|
|
BIOME_HIGH_HUMIDITY = /datum/biome/jungle/deep
|
|
)
|
|
)
|
|
|
|
|
|
#undef BIOME_RANDOM_SQUARE_DRIFT
|
|
#undef CAVE_SPAWN_MOB
|
|
#undef CAVE_SPAWN_FEATURE
|
|
#undef CAVE_SPAWN_TENDRIL
|
|
#undef CAVE_SPAWN_MEGAFAUNA
|