diff --git a/.travis.yml b/.travis.yml
index 0bf4ce5e684..ebd1a8799b7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,7 +11,7 @@ env:
TO_WORLD_COUNT=209
FLYWAY_BUILD="9.9.0"
NODE_VERSION=10
- RUST_G_VERSION="v1.2.0+a2"
+ RUST_G_VERSION="v1.2.0+a4"
PATH=/opt/python/3.7.1/bin:$PATH
SPACEMAN_DMM_VERSION="suite-1.7.3"
matrix:
diff --git a/.versions.sh b/.versions.sh
index 1027fae27e8..be5665f8603 100644
--- a/.versions.sh
+++ b/.versions.sh
@@ -3,6 +3,6 @@
export BYOND_MAJOR=514
export BYOND_MINOR=1589
-export RUST_G_VERSION=v1.2.0+a2
+export RUST_G_VERSION=v1.2.0+a4
export FLYWAY_BUILD=9.9.0
export SPACEMAN_DMM_VERSION=suite-1.7.3
diff --git a/aurorastation.dme b/aurorastation.dme
index 7472a5fa855..cecc55437a4 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -1145,11 +1145,9 @@
#include "code\game\objects\structures\lattice.dm"
#include "code\game\objects\structures\light_pole.dm"
#include "code\game\objects\structures\mirror.dm"
-#include "code\game\objects\structures\monolith.dm"
#include "code\game\objects\structures\mop_bucket.dm"
#include "code\game\objects\structures\morgue.dm"
#include "code\game\objects\structures\noticeboard.dm"
-#include "code\game\objects\structures\pit.dm"
#include "code\game\objects\structures\plasticflaps.dm"
#include "code\game\objects\structures\railing.dm"
#include "code\game\objects\structures\safe.dm"
@@ -1201,12 +1199,6 @@
#include "code\game\objects\structures\crates_lockers\closets\secure\security.dm"
#include "code\game\objects\structures\crates_lockers\closets\secure\service.dm"
#include "code\game\objects\structures\crates_lockers\crates\gear_loadout.dm"
-#include "code\game\objects\structures\flora\adhomai.dm"
-#include "code\game\objects\structures\flora\generic_flora.dm"
-#include "code\game\objects\structures\flora\grove.dm"
-#include "code\game\objects\structures\flora\jungle.dm"
-#include "code\game\objects\structures\flora\potted.dm"
-#include "code\game\objects\structures\flora\snow.dm"
#include "code\game\objects\structures\gore\core.dm"
#include "code\game\objects\structures\gore\nest.dm"
#include "code\game\objects\structures\gore\tendrils.dm"
@@ -2106,7 +2098,9 @@
#include "code\modules\maps\reader.dm"
#include "code\modules\maps\ruins.dm"
#include "code\modules\maps\swapmaps.dm"
+#include "code\modules\maps\planet_types\asteroid.dm"
#include "code\modules\maps\planet_types\barren.dm"
+#include "code\modules\maps\planet_types\crystal.dm"
#include "code\modules\maps\planet_types\desert.dm"
#include "code\modules\maps\planet_types\grass.dm"
#include "code\modules\maps\planet_types\jungle.dm"
@@ -2667,9 +2661,50 @@
#include "code\modules\overmap\events\event.dm"
#include "code\modules\overmap\exoplanets\exoplanet.dm"
#include "code\modules\overmap\exoplanets\exoplanet_skybox.dm"
-#include "code\modules\overmap\exoplanets\random_map.dm"
-#include "code\modules\overmap\exoplanets\theme.dm"
-#include "code\modules\overmap\exoplanets\turfs.dm"
+#include "code\modules\overmap\exoplanets\_defines\planetgen.dm"
+#include "code\modules\overmap\exoplanets\biomes\_biome.dm"
+#include "code\modules\overmap\exoplanets\biomes\barren.dm"
+#include "code\modules\overmap\exoplanets\biomes\crystal.dm"
+#include "code\modules\overmap\exoplanets\biomes\desert.dm"
+#include "code\modules\overmap\exoplanets\biomes\grass.dm"
+#include "code\modules\overmap\exoplanets\biomes\jungle.dm"
+#include "code\modules\overmap\exoplanets\biomes\lava.dm"
+#include "code\modules\overmap\exoplanets\biomes\marsh.dm"
+#include "code\modules\overmap\exoplanets\biomes\snow.dm"
+#include "code\modules\overmap\exoplanets\decor\_areas.dm"
+#include "code\modules\overmap\exoplanets\decor\_flora.dm"
+#include "code\modules\overmap\exoplanets\decor\_turfs.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\_bush.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\_rock.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\_tree.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\adhomai.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\crystal.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\desert.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\generic_flora.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\grove.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\jungle.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\marsh.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\potted.dm"
+#include "code\modules\overmap\exoplanets\decor\flora\snow.dm"
+#include "code\modules\overmap\exoplanets\decor\objs\monolith.dm"
+#include "code\modules\overmap\exoplanets\decor\objs\pit.dm"
+#include "code\modules\overmap\exoplanets\decor\turfs\barren.dm"
+#include "code\modules\overmap\exoplanets\decor\turfs\concrete.dm"
+#include "code\modules\overmap\exoplanets\decor\turfs\crystal.dm"
+#include "code\modules\overmap\exoplanets\decor\turfs\grass.dm"
+#include "code\modules\overmap\exoplanets\decor\turfs\ice.dm"
+#include "code\modules\overmap\exoplanets\decor\turfs\mineral.dm"
+#include "code\modules\overmap\exoplanets\decor\turfs\sand.dm"
+#include "code\modules\overmap\exoplanets\decor\turfs\snow.dm"
+#include "code\modules\overmap\exoplanets\decor\turfs\water.dm"
+#include "code\modules\overmap\exoplanets\themes\_theme.dm"
+#include "code\modules\overmap\exoplanets\themes\barren.dm"
+#include "code\modules\overmap\exoplanets\themes\crystal.dm"
+#include "code\modules\overmap\exoplanets\themes\desert.dm"
+#include "code\modules\overmap\exoplanets\themes\grass.dm"
+#include "code\modules\overmap\exoplanets\themes\jungle.dm"
+#include "code\modules\overmap\exoplanets\themes\lava.dm"
+#include "code\modules\overmap\exoplanets\themes\snow.dm"
#include "code\modules\overmap\ship_weaponry\_ship_ammo_loader.dm"
#include "code\modules\overmap\ship_weaponry\_ship_ammunition.dm"
#include "code\modules\overmap\ship_weaponry\_ship_gun.dm"
diff --git a/code/__defines/ruin_tags.dm b/code/__defines/ruin_tags.dm
index 3f7e724ac91..20ff99bea79 100644
--- a/code/__defines/ruin_tags.dm
+++ b/code/__defines/ruin_tags.dm
@@ -23,6 +23,8 @@
#define PLANET_GRASS BITFLAG(4)
#define PLANET_LAVA BITFLAG(5)
#define PLANET_SNOW BITFLAG(6)
+#define PLANET_MARSH BITFLAG(7)
+#define PLANET_CRYSTAL BITFLAG(8)
-#define ALL_PLANET_TYPES PLANET_BARREN|PLANET_ASTEROID|PLANET_DESERT|PLANET_GROVE|PLANET_GRASS|PLANET_LAVA|PLANET_SNOW
+#define ALL_PLANET_TYPES PLANET_BARREN|PLANET_ASTEROID|PLANET_DESERT|PLANET_GROVE|PLANET_GRASS|PLANET_LAVA|PLANET_SNOW|PLANET_MARSH|PLANET_CRYSTAL
#define PLANET_LORE BITFLAG(16)
diff --git a/code/__defines/rust_g.dm b/code/__defines/rust_g.dm
index ddbc97cb0e9..a56d77b3e5b 100644
--- a/code/__defines/rust_g.dm
+++ b/code/__defines/rust_g.dm
@@ -38,8 +38,15 @@
#define RUST_G (__rust_g || __detect_rust_g())
#endif
+// Handle 515 call() -> call_ext() changes
+#if DM_VERSION >= 515
+#define RUSTG_CALL call_ext
+#else
+#define RUSTG_CALL call
+#endif
+
/// Gets the version of rust_g
-/proc/rustg_get_version() return LIBCALL(RUST_G, "get_version")()
+/proc/rustg_get_version() return RUSTG_CALL(RUST_G, "get_version")()
/**
@@ -51,7 +58,7 @@
* * patterns - A non-associative list of strings to search for
* * replacements - Default replacements for this automaton, used with rustg_acreplace
*/
-#define rustg_setup_acreplace(key, patterns, replacements) LIBCALL(RUST_G, "setup_acreplace")(key, json_encode(patterns), json_encode(replacements))
+#define rustg_setup_acreplace(key, patterns, replacements) RUSTG_CALL(RUST_G, "setup_acreplace")(key, json_encode(patterns), json_encode(replacements))
/**
* Sets up the Aho-Corasick automaton using supplied options.
@@ -63,7 +70,7 @@
* * patterns - A non-associative list of strings to search for
* * replacements - Default replacements for this automaton, used with rustg_acreplace
*/
-#define rustg_setup_acreplace_with_options(key, options, patterns, replacements) LIBCALL(RUST_G, "setup_acreplace")(key, json_encode(options), json_encode(patterns), json_encode(replacements))
+#define rustg_setup_acreplace_with_options(key, options, patterns, replacements) RUSTG_CALL(RUST_G, "setup_acreplace")(key, json_encode(options), json_encode(patterns), json_encode(replacements))
/**
* Run the specified replacement engine with the provided haystack text to replace, returning replaced text.
@@ -72,7 +79,7 @@
* * key - The key for the automaton
* * text - Text to run replacements on
*/
-#define rustg_acreplace(key, text) LIBCALL(RUST_G, "acreplace")(key, text)
+#define rustg_acreplace(key, text) RUSTG_CALL(RUST_G, "acreplace")(key, text)
/**
* Run the specified replacement engine with the provided haystack text to replace, returning replaced text.
@@ -82,7 +89,7 @@
* * text - Text to run replacements on
* * replacements - Replacements for this call. Must be the same length as the set-up patterns
*/
-#define rustg_acreplace_with_replacements(key, text, replacements) LIBCALL(RUST_G, "acreplace_with_replacements")(key, text, json_encode(replacements))
+#define rustg_acreplace_with_replacements(key, text, replacements) RUSTG_CALL(RUST_G, "acreplace_with_replacements")(key, text, json_encode(replacements))
/**
* This proc generates a cellular automata noise grid which can be used in procedural generation methods.
@@ -98,31 +105,48 @@
* * height: The height of the grid.
*/
#define rustg_cnoise_generate(percentage, smoothing_iterations, birth_limit, death_limit, width, height) \
- LIBCALL(RUST_G, "cnoise_generate")(percentage, smoothing_iterations, birth_limit, death_limit, width, height)
+ RUSTG_CALL(RUST_G, "cnoise_generate")(percentage, smoothing_iterations, birth_limit, death_limit, width, height)
-#define rustg_dmi_strip_metadata(fname) LIBCALL(RUST_G, "dmi_strip_metadata")(fname)
-#define rustg_dmi_create_png(path, width, height, data) LIBCALL(RUST_G, "dmi_create_png")(path, width, height, data)
-#define rustg_dmi_resize_png(path, width, height, resizetype) LIBCALL(RUST_G, "dmi_resize_png")(path, width, height, resizetype)
+/**
+ * This proc generates a grid of perlin-like noise
+ *
+ * Returns a single string that goes row by row, with values of 1 representing an turned on cell, and a value of 0 representing a turned off cell.
+ *
+ * Arguments:
+ * * seed: seed for the function
+ * * accuracy: how close this is to the original perlin noise, as accuracy approaches infinity, the noise becomes more and more perlin-like
+ * * stamp_size: Size of a singular stamp used by the algorithm, think of this as the same stuff as frequency in perlin noise
+ * * world_size: size of the returned grid.
+ * * lower_range: lower bound of values selected for. (inclusive)
+ * * upper_range: upper bound of values selected for. (exclusive)
+ */
+#define rustg_dbp_generate(seed, accuracy, stamp_size, world_size, lower_range, upper_range) \
+ RUSTG_CALL(RUST_G, "dbp_generate")(seed, accuracy, stamp_size, world_size, lower_range, upper_range)
-#define rustg_file_read(fname) LIBCALL(RUST_G, "file_read")(fname)
-#define rustg_file_exists(fname) LIBCALL(RUST_G, "file_exists")(fname)
-#define rustg_file_write(text, fname) LIBCALL(RUST_G, "file_write")(text, fname)
-#define rustg_file_append(text, fname) LIBCALL(RUST_G, "file_append")(text, fname)
-#define rustg_file_get_line_count(fname) text2num(LIBCALL(RUST_G, "file_get_line_count")(fname))
-#define rustg_file_seek_line(fname, line) LIBCALL(RUST_G, "file_seek_line")(fname, "[line]")
+
+#define rustg_dmi_strip_metadata(fname) RUSTG_CALL(RUST_G, "dmi_strip_metadata")(fname)
+#define rustg_dmi_create_png(path, width, height, data) RUSTG_CALL(RUST_G, "dmi_create_png")(path, width, height, data)
+#define rustg_dmi_resize_png(path, width, height, resizetype) RUSTG_CALL(RUST_G, "dmi_resize_png")(path, width, height, resizetype)
+
+#define rustg_file_read(fname) RUSTG_CALL(RUST_G, "file_read")(fname)
+#define rustg_file_exists(fname) RUSTG_CALL(RUST_G, "file_exists")(fname)
+#define rustg_file_write(text, fname) RUSTG_CALL(RUST_G, "file_write")(text, fname)
+#define rustg_file_append(text, fname) RUSTG_CALL(RUST_G, "file_append")(text, fname)
+#define rustg_file_get_line_count(fname) text2num(RUSTG_CALL(RUST_G, "file_get_line_count")(fname))
+#define rustg_file_seek_line(fname, line) RUSTG_CALL(RUST_G, "file_seek_line")(fname, "[line]")
#ifdef RUSTG_OVERRIDE_BUILTINS
#define file2text(fname) rustg_file_read("[fname]")
#define text2file(text, fname) rustg_file_append(text, "[fname]")
#endif
-#define rustg_git_revparse(rev) LIBCALL(RUST_G, "rg_git_revparse")(rev)
-#define rustg_git_commit_date(rev) LIBCALL(RUST_G, "rg_git_commit_date")(rev)
+#define rustg_git_revparse(rev) RUSTG_CALL(RUST_G, "rg_git_revparse")(rev)
+#define rustg_git_commit_date(rev) RUSTG_CALL(RUST_G, "rg_git_commit_date")(rev)
-#define rustg_hash_string(algorithm, text) LIBCALL(RUST_G, "hash_string")(algorithm, text)
-#define rustg_hash_file(algorithm, fname) LIBCALL(RUST_G, "hash_file")(algorithm, fname)
-#define rustg_hash_generate_totp(seed) LIBCALL(RUST_G, "generate_totp")(seed)
-#define rustg_hash_generate_totp_tolerance(seed, tolerance) LIBCALL(RUST_G, "generate_totp_tolerance")(seed, tolerance)
+#define rustg_hash_string(algorithm, text) RUSTG_CALL(RUST_G, "hash_string")(algorithm, text)
+#define rustg_hash_file(algorithm, fname) RUSTG_CALL(RUST_G, "hash_file")(algorithm, fname)
+#define rustg_hash_generate_totp(seed) RUSTG_CALL(RUST_G, "generate_totp")(seed)
+#define rustg_hash_generate_totp_tolerance(seed, tolerance) RUSTG_CALL(RUST_G, "generate_totp_tolerance")(seed, tolerance)
#define RUSTG_HASH_MD5 "md5"
#define RUSTG_HASH_SHA1 "sha1"
@@ -141,36 +165,37 @@
#define RUSTG_HTTP_METHOD_PATCH "patch"
#define RUSTG_HTTP_METHOD_HEAD "head"
#define RUSTG_HTTP_METHOD_POST "post"
-#define rustg_http_request_blocking(method, url, body, headers, options) LIBCALL(RUST_G, "http_request_blocking")(method, url, body, headers, options)
-#define rustg_http_request_async(method, url, body, headers, options) LIBCALL(RUST_G, "http_request_async")(method, url, body, headers, options)
-#define rustg_http_check_request(req_id) LIBCALL(RUST_G, "http_check_request")(req_id)
+#define rustg_http_request_blocking(method, url, body, headers, options) RUSTG_CALL(RUST_G, "http_request_blocking")(method, url, body, headers, options)
+#define rustg_http_request_async(method, url, body, headers, options) RUSTG_CALL(RUST_G, "http_request_async")(method, url, body, headers, options)
+#define rustg_http_check_request(req_id) RUSTG_CALL(RUST_G, "http_check_request")(req_id)
#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
#define RUSTG_JOB_ERROR "JOB PANICKED"
-#define rustg_json_is_valid(text) (LIBCALL(RUST_G, "json_is_valid")(text) == "true")
+#define rustg_json_is_valid(text) (RUSTG_CALL(RUST_G, "json_is_valid")(text) == "true")
-#define rustg_log_write(fname, text, format) LIBCALL(RUST_G, "log_write")(fname, text, format)
-/proc/rustg_log_close_all() return LIBCALL(RUST_G, "log_close_all")()
+#define rustg_log_write(fname, text, format) RUSTG_CALL(RUST_G, "log_write")(fname, text, format)
+/proc/rustg_log_close_all() return RUSTG_CALL(RUST_G, "log_close_all")()
-#define rustg_noise_get_at_coordinates(seed, x, y) LIBCALL(RUST_G, "noise_get_at_coordinates")(seed, x, y)
+#define rustg_noise_get_at_coordinates(seed, x, y) RUSTG_CALL(RUST_G, "noise_get_at_coordinates")(seed, x, y)
+#define rustg_noise_poisson_sample(seed, x, y, r) RUSTG_CALL(RUST_G, "generate_poisson_sample")(seed, x, y, r)
-#define rustg_sql_connect_pool(options) LIBCALL(RUST_G, "sql_connect_pool")(options)
-#define rustg_sql_query_async(handle, query, params) LIBCALL(RUST_G, "sql_query_async")(handle, query, params)
-#define rustg_sql_query_blocking(handle, query, params) LIBCALL(RUST_G, "sql_query_blocking")(handle, query, params)
-#define rustg_sql_connected(handle) LIBCALL(RUST_G, "sql_connected")(handle)
-#define rustg_sql_disconnect_pool(handle) LIBCALL(RUST_G, "sql_disconnect_pool")(handle)
-#define rustg_sql_check_query(job_id) LIBCALL(RUST_G, "sql_check_query")("[job_id]")
+#define rustg_sql_connect_pool(options) RUSTG_CALL(RUST_G, "sql_connect_pool")(options)
+#define rustg_sql_query_async(handle, query, params) RUSTG_CALL(RUST_G, "sql_query_async")(handle, query, params)
+#define rustg_sql_query_blocking(handle, query, params) RUSTG_CALL(RUST_G, "sql_query_blocking")(handle, query, params)
+#define rustg_sql_connected(handle) RUSTG_CALL(RUST_G, "sql_connected")(handle)
+#define rustg_sql_disconnect_pool(handle) RUSTG_CALL(RUST_G, "sql_disconnect_pool")(handle)
+#define rustg_sql_check_query(job_id) RUSTG_CALL(RUST_G, "sql_check_query")("[job_id]")
-#define rustg_time_microseconds(id) text2num(LIBCALL(RUST_G, "time_microseconds")(id))
-#define rustg_time_milliseconds(id) text2num(LIBCALL(RUST_G, "time_milliseconds")(id))
-#define rustg_time_reset(id) LIBCALL(RUST_G, "time_reset")(id)
+#define rustg_time_microseconds(id) text2num(RUSTG_CALL(RUST_G, "time_microseconds")(id))
+#define rustg_time_milliseconds(id) text2num(RUSTG_CALL(RUST_G, "time_milliseconds")(id))
+#define rustg_time_reset(id) RUSTG_CALL(RUST_G, "time_reset")(id)
/proc/rustg_unix_timestamp()
- return text2num(LIBCALL(RUST_G, "unix_timestamp")())
+ return text2num(RUSTG_CALL(RUST_G, "unix_timestamp")())
-#define rustg_raw_read_toml_file(path) json_decode(LIBCALL(RUST_G, "toml_file_to_json")(path) || "null")
+#define rustg_raw_read_toml_file(path) json_decode(RUSTG_CALL(RUST_G, "toml_file_to_json")(path) || "null")
/proc/rustg_read_toml_file(path)
var/list/output = rustg_raw_read_toml_file(path)
@@ -179,7 +204,7 @@
else
CRASH(output["content"])
-#define rustg_raw_toml_encode(value) json_decode(LIBCALL(RUST_G, "toml_encode")(json_encode(value)))
+#define rustg_raw_toml_encode(value) json_decode(RUSTG_CALL(RUST_G, "toml_encode")(json_encode(value)))
/proc/rustg_toml_encode(value)
var/list/output = rustg_raw_toml_encode(value)
@@ -188,10 +213,10 @@
else
CRASH(output["content"])
-#define rustg_udp_send(addr, text) LIBCALL(RUST_G, "udp_send")(addr, text)
+#define rustg_udp_send(addr, text) call(RUST_G, "udp_send")(addr, text)
-#define rustg_url_encode(text) LIBCALL(RUST_G, "url_encode")("[text]")
-#define rustg_url_decode(text) LIBCALL(RUST_G, "url_decode")(text)
+#define rustg_url_encode(text) RUSTG_CALL(RUST_G, "url_encode")("[text]")
+#define rustg_url_decode(text) RUSTG_CALL(RUST_G, "url_decode")(text)
#ifdef RUSTG_OVERRIDE_BUILTINS
#define url_encode(text) rustg_url_encode(text)
diff --git a/code/_helpers/maths.dm b/code/_helpers/maths.dm
index 976cdb054bb..416fcaf1ac3 100644
--- a/code/_helpers/maths.dm
+++ b/code/_helpers/maths.dm
@@ -115,13 +115,10 @@
if(discriminant != 0)
. += (-b - root) / bottom
-/proc/ToDegrees(radians)
- // 180 / Pi ~ 57.2957795
- return radians * 57.2957795
-
-/proc/ToRadians(degrees)
- // Pi / 180 ~ 0.0174532925
- return degrees * 0.0174532925
+/// 180 / Pi ~ 57.2957795
+#define TO_DEGREES(radians) ((radians) * 57.2957795)
+/// Pi / 180 ~ 0.0174532925
+#define TO_RADIANS(degrees) ((degrees) * 0.0174532925)
// Vector algebra.
/proc/squaredNorm(x, y)
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index 190523c3935..7605acbf2eb 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -30,8 +30,11 @@
weakref = null
destroyed_event.raise_event(src)
- SSnanoui.close_uis(src)
- SSvueui.close_uis(src)
+ var/ui_key = SOFTREF(src)
+ if(LAZYISIN(SSnanoui.open_uis, ui_key))
+ SSnanoui.close_uis(src)
+ if(LAZYISIN(SSvueui.open_uis, ui_key))
+ SSvueui.close_uis(src)
tag = null
var/list/timers = active_timers
active_timers = null
diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm
index eff65451c3c..a847454ebd6 100644
--- a/code/game/objects/effects/chem/chemsmoke.dm
+++ b/code/game/objects/effects/chem/chemsmoke.dm
@@ -208,7 +208,7 @@
var/offset = 0
var/points = round((radius * 2 * M_PI) / arcLength)
- var/angle = round(ToDegrees(arcLength / radius), 1)
+ var/angle = round(TO_DEGREES(arcLength / radius), 1)
if(!IsInteger(radius))
offset = 45 //degrees
diff --git a/code/game/objects/effects/decals/snow.dm b/code/game/objects/effects/decals/snow.dm
index f188077632d..20d08febfd0 100644
--- a/code/game/objects/effects/decals/snow.dm
+++ b/code/game/objects/effects/decals/snow.dm
@@ -9,9 +9,19 @@
icon_state = "snow_surround"
/obj/effect/floor_decal/snowdrift
+ name = "snow drift"
icon = 'icons/turf/snow.dmi'
icon_state = "drift"
+/obj/effect/floor_decal/snowdrift/random/Initialize(mapload, newdir, newcolour, bypass, set_icon_state)
+ supplied_dir = pick(cardinal)
+ return ..()
+
/obj/effect/floor_decal/snowdrift/large
+ name = "snow drift (large)"
icon = 'icons/turf/decals/snow64x32.dmi'
pixel_x = -16
+
+/obj/effect/floor_decal/snowdrift/large/random/Initialize(mapload, newdir, newcolour, bypass, set_icon_state)
+ supplied_dir = pick(cardinal)
+ return ..()
diff --git a/code/game/objects/structures/flora/generic_flora.dm b/code/game/objects/structures/flora/generic_flora.dm
deleted file mode 100644
index 241565393b7..00000000000
--- a/code/game/objects/structures/flora/generic_flora.dm
+++ /dev/null
@@ -1,385 +0,0 @@
-/obj/structure/flora
- name = "flora parent object"
- desc = DESC_PARENT
- anchored = TRUE
- density = TRUE
- var/cutting
-
-/obj/structure/flora/proc/dig_up(mob/user)
- user.visible_message(SPAN_NOTICE("\The [user] begins digging up \the [src]..."))
- if(do_after(user, 150))
- if(Adjacent(user))
- user.visible_message(SPAN_NOTICE("\The [user] removes \the [src]!"))
- qdel(src)
-
-/obj/structure/flora/proc/can_dig()
- return FALSE
-
-/obj/structure/flora/attackby(obj/item/I, mob/user)
- if(I.is_shovel() && can_dig())
- dig_up(user)
- return
- ..()
-
-/obj/structure/flora/tree
- name = "tree"
- desc = "A tree."
- density = TRUE
- layer = 9
- pixel_x = -16
- var/max_chop_health = 180
- var/chop_health = 180 //15 hits with steel hatchet, 5 with wielded fireaxe
- var/fall_force = 60
- var/list/contained_objects = list() //If it has anything except wood. Fruit, pinecones, animals, etc.
- var/stumptype = /obj/structure/flora/stump //stump to make when chopped
- var/static/list/fall_forbid = list(/obj/structure/flora, /obj/effect, /obj/structure/bonfire, /obj/structure/pit)
-
-/obj/structure/flora/tree/proc/update_desc()
- desc = initial(desc)
- switch(chop_health / max_chop_health)
- if(0 to 0.25)
- desc = " It looks like it's about to fall!"
- if(0.26 to 0.5)
- desc += " Just a bit more work and it'll fall!"
- if(0.51 to 0.75)
- desc += " It's been chopped at a few times."
- if(0.76 to 0.95)
- desc += " Looks like someone just started cutting it down."
-
-/obj/structure/flora/tree/attackby(obj/item/I, mob/user)
- if(I.can_woodcut())
- if(cutting)
- return
- user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
- cutting = TRUE
- if(istype(I, /obj/item/material/twohanded/chainsaw))
- var/obj/item/material/twohanded/chainsaw/C = I
- if(C.powered)
- user.visible_message(SPAN_NOTICE("\The [user] begins cutting down \the [src]..."), SPAN_NOTICE("You start cutting down \the [src]..."))
- playsound(get_turf(user), 'sound/weapons/saw/chainsawhit.ogg', 60, 1)
- shake_animation()
- if(do_after(user, 50))
- timber(user)
- else
- to_chat(user, SPAN_WARNING("Try turning \the [C] on first!"))
- cutting = FALSE
- return
- else if(do_after(user, I.w_class * 5)) //Small windup
- user.do_attack_animation(src)
- shake_animation()
- playsound(get_turf(src), 'sound/effects/woodcutting.ogg', 50, 1)
- chop_health -= I.force
- update_desc()
- if(prob(20))
- user.visible_message(SPAN_NOTICE("\The [user] chops at \the [src]."), SPAN_NOTICE("You chop at \the [src]."), SPAN_NOTICE("You hear someone chopping wood."))
- if(prob(I.force/3))
- var/list/valid_turfs = list()
- for(var/turf/T in circle_range(src, 1))
- if(T.contains_dense_objects())
- continue
- valid_turfs += T
- if(!valid_turfs.len)
- valid_turfs += get_turf(src)
- var/obj/item/stack/material/wood/branch/B = new(pick(valid_turfs))
- B.amount = 1
- visible_message(SPAN_NOTICE("\The [B] falls from \the [src]."))
-
- if(chop_health <= 0)
- timber(user)
- cutting = FALSE
- return
- ..()
-
-/obj/structure/flora/tree/proc/timber(mob/user)
- var/turf/fall_loc //Where we will fall
-
- //We prefer to fall directly away from the user if possible
- var/turf/pref_loc = get_cardinal_step_away(src, user)
- if(!pref_loc.contains_dense_objects(TRUE))
- fall_loc = pref_loc
-
- //Otherwise, we fall elsewhere
- else
- var/list/fall_spots = list()
- for(var/turf/T in orange(1, src))
- if(locate(user) in T.contents) //Won't fall on woodcutter
- continue
- if(T.contains_dense_objects(TRUE)) //Let's avoid dense objects but not mobs
- continue
- fall_spots += T
-
- if(!fall_spots.len)
- fall_loc = get_turf(src)
- else
- fall_loc = pick(fall_spots)
- playsound(get_turf(src), 'sound/species/diona/gestalt_grow.ogg', 50)
- for(var/atom/A in fall_loc.contents)
- if(is_type_in_list(A, fall_forbid))
- continue
- if(isliving(A))
- var/mob/living/L = A
- visible_message(SPAN_WARNING("\The [src] crushes \the [L] under its weight!"))
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- var/obj/item/organ/external/affected = pick(H.organs)
- affected.take_damage(fall_force)
- else
- if(L.mob_size <= fall_force / 5)
- L.gib()
- else
- L.health -= fall_force
- if(L.health <= 0)
- L.gib()
-
- if(isobj(A) && !istype(A, /obj/item/stack) && A != src)
- var/obj/O = A
- if(prob(fall_force * 0.75))
- visible_message(SPAN_WARNING("\The [src] crushes \the [O] under its weight!"))
- qdel(A)
- new /obj/structure/flora/stump/log(fall_loc)
- var/obj/item/stack/material/wood/branch/B = new(fall_loc)
- B.amount = rand(5, 8)
- new stumptype(get_turf(src))
- qdel(src)
-
-/obj/structure/flora/stump
- name = "stump"
- desc = "Nature's chair."
- icon = 'icons/obj/wood.dmi'
- icon_state = "tree_stump"
- density = FALSE
- anchored = TRUE
-
-/obj/structure/flora/stump/can_dig()
- return TRUE
-
-/obj/structure/flora/stump/log
- name = "big log"
- desc = "A sideways tree, but dead. Chop this into useable logs!"
- anchored = FALSE
- icon_state = "timber"
-
-/obj/structure/flora/stump/log/attackby(obj/item/I, mob/user)
- if(I.can_woodcut())
- if(cutting)
- return
- cutting = TRUE
- var/chopsound = istype(I, /obj/item/material/twohanded/chainsaw) ? 'sound/weapons/saw/chainsawhit.ogg' : 'sound/effects/woodcutting.ogg'
- playsound(get_turf(user), chopsound, 50, 1)
- user.visible_message(SPAN_NOTICE("\The [user] begins chopping \the [src] into log sections."), SPAN_NOTICE("You begin chopping \the [src] into log sections."))
- var/chopspeed = 1
- if(istype(I, /obj/item/material/twohanded))
- var/obj/item/material/twohanded/W = I
- chopspeed = W.wielded ? 2 : 1
- if(do_after(user, 100 / chopspeed))
- user.visible_message(SPAN_NOTICE("\The [user] chops \the [src] into log sections."), SPAN_NOTICE("You chop \the [src] into log sections."))
- var/obj/item/stack/material/wood/log/L = new(get_turf(src))
- L.amount = rand(5, 8)
- qdel(src)
- cutting = FALSE
- else
- ..()
-
-/obj/structure/flora/tree/pine
- name = "pine tree"
- icon = 'icons/obj/flora/pinetrees.dmi'
- icon_state = "pine_1"
-
-/obj/structure/flora/tree/pine/New()
- ..()
- icon_state = "pine_[rand(1, 3)]"
-
-/obj/structure/flora/tree/pine/xmas
- name = "xmas tree"
- icon = 'icons/obj/flora/pinetrees.dmi'
- icon_state = "pine_c"
-
-/obj/structure/flora/tree/pine/xmas/New()
- ..()
- icon_state = "pine_c"
-
-/obj/structure/flora/tree/dead
- icon = 'icons/obj/flora/deadtrees.dmi'
- icon_state = "tree_1"
-
-/obj/structure/flora/tree/dead/New()
- ..()
- icon_state = "tree_[rand(1, 6)]"
-
-/obj/structure/flora/tree/jungle/small/patience
- name = "Patience"
- desc = "A lush and healthy tree. A small golden plaque at its base reads its name, in plain text, Patience."
- icon_state = "patiencebottom"
- density = FALSE
- layer = 3
-
-/obj/structure/flora/tree/jungle/small/patience_top
- name = "Patience"
- desc = "A lush and healthy tree. A small golden plaque at its base reads its name, in plain text, Patience."
- icon_state = "patiencetop"
- density = TRUE
- pixel_y = -32
-
-/obj/structure/flora/tree/jungle/small/patience/Initialize()
- . = ..()
- var/turf/T = get_step(src, NORTH)
- if(T)
- new /obj/structure/flora/tree/jungle/small/patience_top(T)
-
-// Rocks
-/obj/structure/flora/rock
- name = "rock"
- desc = "A rock."
- icon = 'icons/obj/flora/rocks_grey.dmi'
- icon_state = "basalt"
-
-/obj/structure/flora/rock/pile
- name = "rocks"
- desc = "A pile of rocks."
- icon_state = "lavarocks"
-
-/obj/structure/flora/rock/ice
- name = "ice"
- desc = "A large formation made of ice."
- icon = 'icons/obj/flora/ice_rocks.dmi'
- icon_state = "rock_1"
-
-/obj/structure/flora/rock/ice/Initialize(mapload)
- . = ..()
- icon_state = "rock_[rand(1,2)]"
-
-// Bushes, Flowers, and Grass
-/obj/structure/flora/ausbushes
- name = "bush"
- desc = "A bush."
- icon = 'icons/obj/flora/ausflora.dmi'
- icon_state = "firstbush_1"
- density = FALSE
-
-/obj/structure/flora/ausbushes/New()
- ..()
- icon_state = "firstbush_[rand(1, 4)]"
-
-/obj/structure/flora/ausbushes/attackby(var/obj/item/W, var/mob/user)
- if(istype(W, /obj/item/material/scythe))
- if(prob(50))
- new /obj/item/stack/material/wood(get_turf(src), 2)
- if(prob(40))
- new /obj/item/stack/material/wood(get_turf(src), 4)
- if(prob(10))
- var/pickberry = pick(list(/obj/item/seeds/berryseed, /obj/item/seeds/blueberryseed))
- new /obj/item/stack/material/wood(get_turf(src), 4)
- new pickberry(get_turf(src), 4)
- to_chat(user, SPAN_NOTICE("You find some seeds as you hack the bush away."))
- to_chat(user, SPAN_NOTICE("You slice at the bush!"))
- qdel(src)
- playsound(src, 'sound/effects/woodcutting.ogg', 50, TRUE)
- if(istype(W, /obj/item/material/hatchet)) // No items.
- to_chat(user, SPAN_NOTICE("You chop at the bush!"))
- qdel(src)
- playsound(src, 'sound/effects/woodcutting.ogg', 50, TRUE)
-
-/obj/structure/flora/ausbushes/reedbush
- icon_state = "reedbush_1"
-
-/obj/structure/flora/ausbushes/reedbush/New()
- ..()
- icon_state = "reedbush_[rand(1, 4)]"
-
-/obj/structure/flora/ausbushes/leafybush
- icon_state = "leafybush_1"
-
-/obj/structure/flora/ausbushes/leafybush/New()
- ..()
- icon_state = "leafybush_[rand(1, 3)]"
-
-/obj/structure/flora/ausbushes/palebush
- icon_state = "palebush_1"
-
-/obj/structure/flora/ausbushes/palebush/New()
- ..()
- icon_state = "palebush_[rand(1, 4)]"
-
-/obj/structure/flora/ausbushes/stalkybush
- icon_state = "stalkybush_1"
-
-/obj/structure/flora/ausbushes/stalkybush/New()
- ..()
- icon_state = "stalkybush_[rand(1, 3)]"
-
-/obj/structure/flora/ausbushes/grassybush
- icon_state = "grassybush_1"
-
-/obj/structure/flora/ausbushes/grassybush/New()
- ..()
- icon_state = "grassybush_[rand(1, 4)]"
-
-/obj/structure/flora/ausbushes/fernybush
- icon_state = "fernybush_1"
-
-/obj/structure/flora/ausbushes/fernybush/New()
- ..()
- icon_state = "fernybush_[rand(1, 3)]"
-
-/obj/structure/flora/ausbushes/sunnybush
- icon_state = "sunnybush_1"
-
-/obj/structure/flora/ausbushes/sunnybush/New()
- ..()
- icon_state = "sunnybush_[rand(1, 3)]"
-
-/obj/structure/flora/ausbushes/genericbush
- icon_state = "genericbush_1"
-
-/obj/structure/flora/ausbushes/genericbush/New()
- ..()
- icon_state = "genericbush_[rand(1, 4)]"
-
-/obj/structure/flora/ausbushes/pointybush
- icon_state = "pointybush_1"
-
-/obj/structure/flora/ausbushes/pointybush/New()
- ..()
- icon_state = "pointybush_[rand(1, 4)]"
-
-/obj/structure/flora/ausbushes/lavendergrass
- icon_state = "lavendergrass_1"
-
-/obj/structure/flora/ausbushes/lavendergrass/New()
- ..()
- icon_state = "lavendergrass_[rand(1, 4)]"
-
-/obj/structure/flora/ausbushes/ywflowers
- icon_state = "ywflowers_1"
-
-/obj/structure/flora/ausbushes/ywflowers/New()
- ..()
- icon_state = "ywflowers_[rand(1, 3)]"
-
-/obj/structure/flora/ausbushes/brflowers
- icon_state = "brflowers_1"
-
-/obj/structure/flora/ausbushes/brflowers/New()
- ..()
- icon_state = "brflowers_[rand(1, 3)]"
-
-/obj/structure/flora/ausbushes/ppflowers
- icon_state = "ppflowers_1"
-
-/obj/structure/flora/ausbushes/ppflowers/New()
- ..()
- icon_state = "ppflowers_[rand(1, 4)]"
-
-/obj/structure/flora/ausbushes/sparsegrass
- icon_state = "sparsegrass_1"
-
-/obj/structure/flora/ausbushes/sparsegrass/New()
- ..()
- icon_state = "sparsegrass_[rand(1, 3)]"
-
-/obj/structure/flora/ausbushes/fullgrass
- icon_state = "fullgrass_1"
-
-/obj/structure/flora/ausbushes/fullgrass/New()
- ..()
- icon_state = "fullgrass_[rand(1, 3)]"
\ No newline at end of file
diff --git a/code/game/objects/structures/flora/jungle.dm b/code/game/objects/structures/flora/jungle.dm
deleted file mode 100644
index 3202b7f3de9..00000000000
--- a/code/game/objects/structures/flora/jungle.dm
+++ /dev/null
@@ -1,22 +0,0 @@
-/obj/structure/flora/tree/jungle
- name = "tree"
- icon_state = "tree"
- desc = "A lush and healthy tree."
- icon = 'icons/obj/flora/jungletrees.dmi'
- pixel_x = -48
- pixel_y = -20
-
-/obj/structure/flora/tree/jungle/small
- pixel_y = 0
- pixel_x = -32
- icon = 'icons/obj/flora/jungletreesmall.dmi'
-
-//Jungle grass
-/obj/structure/flora/grass/jungle
- name = "jungle grass"
- desc = "Thick alien flora."
- icon = 'icons/obj/flora/jungleflora.dmi'
- icon_state = "grassa"
-
-/obj/structure/flora/grass/jungle/b
- icon_state = "grassb"
\ No newline at end of file
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 9c99b8ef536..1bbfb6e55ed 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -210,8 +210,8 @@
A.loc.Entered(A)
return
-/turf/space/ChangeTurf(var/turf/N, var/tell_universe=TRUE, var/force_lighting_update = FALSE, keep_air = FALSE)
- return ..(N, tell_universe, TRUE, keep_air)
+/turf/space/ChangeTurf(turf/N, tell_universe=TRUE, force_lighting_update = FALSE, ignore_override = FALSE, mapload = FALSE, keep_air = FALSE)
+ return ..()
/turf/space/is_open()
return TRUE
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 800a1cea38c..5a4babe4382 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -98,11 +98,6 @@
if (z_flags & ZM_MIMIC_BELOW)
setup_zmimic(mapload)
- if (current_map.use_overmap && istype(A, /area/exoplanet))
- var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
- if (istype(E) && istype(E.theme))
- E.theme.on_turf_generation(src, E.planetary_area)
-
return INITIALIZE_HINT_NORMAL
/turf/Destroy()
diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm
index b1622c9085d..92523cbb0ba 100644
--- a/code/game/turfs/turf_changing.dm
+++ b/code/game/turfs/turf_changing.dm
@@ -20,10 +20,10 @@
if(queue_neighbors)
queue_smooth_neighbors(src)
- else
+ else if(smooth && !(smooth & SMOOTH_QUEUED)) // we check here because proc overhead
queue_smooth(src)
- if (current_map.use_overmap && istype(loc, /area/exoplanet))
+ if (current_map.use_overmap)
var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
if (istype(E) && istype(E.theme))
E.theme.on_turf_generation(src, E.planetary_area)
@@ -34,7 +34,7 @@
//Creates a new turf.
// N is the type of the turf.
-/turf/proc/ChangeTurf(N, tell_universe = TRUE, force_lighting_update = FALSE, var/ignore_override)
+/turf/proc/ChangeTurf(N, tell_universe = TRUE, force_lighting_update = FALSE, ignore_override = FALSE, mapload = FALSE)
if (!N)
return
@@ -117,7 +117,7 @@
W.decals = old_decals
- W.post_change()
+ W.post_change(!mapload)
. = W
diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm
index f66579fa899..bf7f5be1093 100644
--- a/code/modules/admin/view_variables/view_variables.dm
+++ b/code/modules/admin/view_variables/view_variables.dm
@@ -6,7 +6,7 @@
// Variables not to expand the lists of. Vars is pointless to expand, and overlays/underlays cannot be expanded.
/var/list/view_variables_dont_expand = list("overlays", "underlays", "vars", "screen", "our_overlays", "priority_overlays", "queued_overlays")
// Variables that runtime if you try to test associativity of the lists they contain by indexing
-/var/list/view_variables_no_assoc = list("verbs", "contents")
+/var/list/view_variables_no_assoc = list("verbs", "contents", "vis_contents")
// Acceptable 'in world', as VV would be incredibly hampered otherwise
/client/proc/debug_variables(datum/D in world)
diff --git a/code/modules/background/space_sectors/tauceti.dm b/code/modules/background/space_sectors/tauceti.dm
index 73b53074ae5..13d4fd6dd67 100644
--- a/code/modules/background/space_sectors/tauceti.dm
+++ b/code/modules/background/space_sectors/tauceti.dm
@@ -112,4 +112,4 @@
possible_exoplanets = list(/obj/effect/overmap/visitable/sector/exoplanet/barren/asteroid, /obj/effect/overmap/visitable/sector/exoplanet/barren, /obj/effect/overmap/visitable/sector/exoplanet/grass/grove)
starlight_color = "#9cd0fd"
starlight_power = 5
- starlight_range = 2
\ No newline at end of file
+ starlight_range = 2
diff --git a/code/modules/integrated_electronics/subtypes/converters.dm b/code/modules/integrated_electronics/subtypes/converters.dm
index 2acf7036e55..cba46c982ae 100644
--- a/code/modules/integrated_electronics/subtypes/converters.dm
+++ b/code/modules/integrated_electronics/subtypes/converters.dm
@@ -227,7 +227,7 @@
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
- result = ToDegrees(incoming)
+ result = TO_DEGREES(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -245,7 +245,7 @@
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(!isnull(incoming))
- result = ToRadians(incoming)
+ result = TO_RADIANS(incoming)
set_pin_data(IC_OUTPUT, 1, result)
push_data()
@@ -353,4 +353,4 @@
set_pin_data(IC_OUTPUT, 1, result)
push_data()
- activate_pin(2)
\ No newline at end of file
+ activate_pin(2)
diff --git a/code/modules/maps/planet_types/asteroid.dm b/code/modules/maps/planet_types/asteroid.dm
new file mode 100644
index 00000000000..7b97d08af06
--- /dev/null
+++ b/code/modules/maps/planet_types/asteroid.dm
@@ -0,0 +1,30 @@
+/obj/effect/overmap/visitable/sector/exoplanet/barren/asteroid
+ name = "mineral asteroid"
+ desc = "A large, resource rich asteroid."
+ massvolume = "Miniscule, not immediately apparent in mass"
+ surfacegravity = "Miniscule, non-obstructive gravity well"
+ surface_color = COLOR_GRAY
+ scanimage = "asteroid.png"
+ possible_themes = list(/datum/exoplanet_theme/barren/asteroid)
+ rock_colors = list(COLOR_ASTEROID_ROCK)
+ planetary_area = /area/exoplanet/barren/asteroid
+ ruin_planet_type = PLANET_ASTEROID
+ ruin_allowed_tags = RUIN_AIRLESS|RUIN_LOWPOP|RUIN_MINING|RUIN_SCIENCE|RUIN_HOSTILE|RUIN_WRECK|RUIN_NATURAL
+
+ place_near_main = list(1, 1)
+
+/obj/effect/overmap/visitable/sector/exoplanet/barren/asteroid/update_icon()
+ icon_state = "asteroid[rand(1,3)]"
+
+/obj/effect/overmap/visitable/sector/exoplanet/barren/asteroid/generate_planet_image()
+ skybox_image = image('icons/skybox/skybox_rock_128.dmi', "bigrock")
+ skybox_image.color = pick(rock_colors)
+ skybox_image.pixel_x = rand(0,64)
+ skybox_image.pixel_y = rand(128,256)
+ skybox_image.appearance_flags = DEFAULT_APPEARANCE_FLAGS | RESET_COLOR
+ skybox_image.blend_mode = BLEND_OVERLAY
+
+/obj/effect/overmap/visitable/sector/exoplanet/barren/asteroid/romanovich
+ name = "romanovich cloud asteroid"
+ desc = "A phoron rich asteroid."
+ possible_themes = list(/datum/exoplanet_theme/barren/asteroid/phoron)
diff --git a/code/modules/maps/planet_types/barren.dm b/code/modules/maps/planet_types/barren.dm
index 5cdbeffe771..3f1a8966d92 100644
--- a/code/modules/maps/planet_types/barren.dm
+++ b/code/modules/maps/planet_types/barren.dm
@@ -5,8 +5,7 @@
scanimage = "barren.png"
planetary_area = /area/exoplanet/barren
rock_colors = list(COLOR_BEIGE, COLOR_GRAY80, COLOR_BROWN)
- possible_themes = list(/datum/exoplanet_theme/mountains)
- map_generators = list(/datum/random_map/noise/exoplanet/barren, /datum/random_map/noise/ore)
+ possible_themes = list(/datum/exoplanet_theme/barren)
features_budget = 6
surface_color = "#807d7a"
water_color = null
@@ -22,81 +21,3 @@
/obj/effect/overmap/visitable/sector/exoplanet/barren/get_surface_color()
return "#6C6251"
-
-/datum/random_map/noise/exoplanet/barren
- descriptor = "barren exoplanet"
- smoothing_iterations = 4
- land_type = /turf/simulated/floor/exoplanet/barren
- flora_prob = 0.1
- flora_diversity = 0
- fauna_prob = 0
-
-/datum/random_map/noise/exoplanet/barren/New()
- if(prob(10))
- flora_diversity = 1
- ..()
-
-/turf/simulated/floor/exoplanet/barren
- name = "ground"
- icon = 'icons/turf/flooring/asteroid.dmi'
- icon_state = "asteroid"
-
-/turf/simulated/floor/exoplanet/barren/update_icon()
- overlays.Cut()
- if(prob(20))
- overlays += image('icons/turf/decals/decals.dmi', "asteroid[rand(0,9)]")
-
-/turf/simulated/floor/exoplanet/barren/Initialize()
- . = ..()
- update_icon()
-
-/area/exoplanet/barren
- name = "\improper Planetary surface"
- ambience = list('sound/effects/wind/wind_2_1.ogg','sound/effects/wind/wind_2_2.ogg','sound/effects/wind/wind_3_1.ogg','sound/effects/wind/wind_4_1.ogg','sound/effects/wind/wind_4_2.ogg','sound/effects/wind/wind_5_1.ogg')
- base_turf = /turf/simulated/floor/exoplanet/barren
-
-//asteroid
-
-/obj/effect/overmap/visitable/sector/exoplanet/barren/asteroid
- name = "mineral asteroid"
- desc = "A large, resource rich asteroid."
- massvolume = "Miniscule, not immediately apparent in mass"
- surfacegravity = "Miniscule, non-obstructive gravity well"
- surface_color = COLOR_GRAY
- scanimage = "asteroid.png"
- map_generators = list(/datum/random_map/noise/exoplanet/barren/asteroid, /datum/random_map/noise/ore/rich)
- rock_colors = list(COLOR_ASTEROID_ROCK)
- planetary_area = /area/exoplanet/barren/asteroid
- ruin_planet_type = PLANET_ASTEROID
- ruin_allowed_tags = RUIN_AIRLESS|RUIN_LOWPOP|RUIN_MINING|RUIN_SCIENCE|RUIN_HOSTILE|RUIN_WRECK|RUIN_NATURAL
-
- place_near_main = list(1, 1)
-
-/obj/effect/overmap/visitable/sector/exoplanet/barren/asteroid/update_icon()
- icon_state = "asteroid[rand(1,3)]"
-
-/obj/effect/overmap/visitable/sector/exoplanet/barren/asteroid/generate_planet_image()
- skybox_image = image('icons/skybox/skybox_rock_128.dmi', "bigrock")
- skybox_image.color = pick(rock_colors)
- skybox_image.pixel_x = rand(0,64)
- skybox_image.pixel_y = rand(128,256)
- skybox_image.appearance_flags = DEFAULT_APPEARANCE_FLAGS | RESET_COLOR
- skybox_image.blend_mode = BLEND_OVERLAY
-
-/obj/effect/overmap/visitable/sector/exoplanet/barren/asteroid/romanovich
- name = "romanovich cloud asteroid"
- desc = "A phoron rich asteroid."
- possible_themes = list(/datum/exoplanet_theme/mountains/phoron)
- map_generators = list(/datum/random_map/noise/exoplanet/barren/asteroid, /datum/random_map/noise/ore/rich/phoron)
-
-/datum/random_map/noise/exoplanet/barren/asteroid
- descriptor = "asteroid exoplanet"
- smoothing_iterations = 4
- land_type = /turf/unsimulated/floor/asteroid/ash
- fauna_prob = 1
- fauna_types = list(/mob/living/simple_animal/hostile/carp/asteroid, /mob/living/simple_animal/hostile/carp/bloater, /mob/living/simple_animal/hostile/carp/shark/reaver,
- /mob/living/simple_animal/hostile/carp/shark/reaver/eel, /mob/living/simple_animal/hostile/gnat)
-
-/area/exoplanet/barren/asteroid
- name = "\improper Asteroid Surface"
- base_turf = /turf/unsimulated/floor/asteroid/ash
diff --git a/code/modules/maps/planet_types/crystal.dm b/code/modules/maps/planet_types/crystal.dm
new file mode 100644
index 00000000000..f254313904a
--- /dev/null
+++ b/code/modules/maps/planet_types/crystal.dm
@@ -0,0 +1,24 @@
+/obj/effect/overmap/visitable/sector/exoplanet/crystal
+ name = "crystalline exoplanet"
+ desc = "A near-airless world whose surface is encrusted with various crystalline minerals."
+ color = "#6ba7f7"
+ scanimage = "barren.png"
+ geology = "Exceptional silica content compared to baseline; minimal tectonic activity present"
+ planetary_area = /area/exoplanet/crystal
+ rock_colors = list(COLOR_BLUE_GRAY, COLOR_PALE_BLUE_GRAY)
+ possible_themes = list(/datum/exoplanet_theme/crystal)
+ features_budget = 6
+ surface_color = null
+ water_color = null
+ ruin_planet_type = PLANET_CRYSTAL
+ ruin_allowed_tags = RUIN_AIRLESS|RUIN_LOWPOP|RUIN_MINING|RUIN_SCIENCE|RUIN_HOSTILE|RUIN_WRECK|RUIN_NATURAL
+
+/obj/effect/overmap/visitable/sector/exoplanet/barren/generate_habitability()
+ return HABITABILITY_BAD
+
+/obj/effect/overmap/visitable/sector/exoplanet/barren/generate_atmosphere()
+ ..()
+ atmosphere.remove_ratio(0.9)
+
+/obj/effect/overmap/visitable/sector/exoplanet/barren/get_surface_color()
+ return "#6ba7f7"
diff --git a/code/modules/maps/planet_types/desert.dm b/code/modules/maps/planet_types/desert.dm
index 8921f7123fe..de32384400c 100644
--- a/code/modules/maps/planet_types/desert.dm
+++ b/code/modules/maps/planet_types/desert.dm
@@ -8,16 +8,14 @@
planetary_area = /area/exoplanet/desert
rock_colors = list(COLOR_BEIGE, COLOR_PALE_YELLOW, COLOR_GRAY80, COLOR_BROWN)
plant_colors = list("#efdd6f","#7b4a12","#e49135","#ba6222","#5c755e","#420d22")
- map_generators = list(/datum/random_map/noise/exoplanet/desert, /datum/random_map/noise/ore)
- possible_themes = list(/datum/exoplanet_theme/mountains/breathable)
+ possible_themes = list(/datum/exoplanet_theme/desert)
surface_color = "#d6cca4"
water_color = null
ruin_planet_type = PLANET_DESERT
ruin_allowed_tags = RUIN_LOWPOP|RUIN_MINING|RUIN_SCIENCE|RUIN_HOSTILE|RUIN_WRECK|RUIN_NATURAL
/obj/effect/overmap/visitable/sector/exoplanet/desert/generate_map()
- if(prob(70))
- lightlevel = rand(5,10)/10 //deserts are usually :lit:
+ lightlevel = rand(5,10)/10 //deserts are usually :lit:
..()
/obj/effect/overmap/visitable/sector/exoplanet/desert/generate_atmosphere()
@@ -43,27 +41,6 @@
S.set_trait(TRAIT_CARNIVOROUS,2)
S.set_trait(TRAIT_SPREAD,0)
-/datum/random_map/noise/exoplanet/desert
- descriptor = "desert exoplanet"
- smoothing_iterations = 4
- land_type = /turf/simulated/floor/exoplanet/desert
-
- flora_prob = 0
- fauna_types = list(/mob/living/simple_animal/thinbug, /mob/living/simple_animal/tindalos)
-
-/datum/random_map/noise/exoplanet/desert/get_additional_spawns(var/value, var/turf/T)
- ..()
- if(is_edge_turf(T))
- return
- var/v = noise2value(value)
- if(v > 6)
- if(prob(10))
- new/obj/structure/quicksand(T)
-
-/area/exoplanet/desert
- ambience = list('sound/effects/wind/desert0.ogg','sound/effects/wind/desert1.ogg','sound/effects/wind/desert2.ogg','sound/effects/wind/desert3.ogg','sound/effects/wind/desert4.ogg','sound/effects/wind/desert5.ogg')
- base_turf = /turf/simulated/floor/exoplanet/desert
-
/obj/structure/quicksand
name = "sand"
icon = 'icons/obj/quicksand.dmi'
diff --git a/code/modules/maps/planet_types/grass.dm b/code/modules/maps/planet_types/grass.dm
index 0b2baf502b0..cd8965cbad3 100644
--- a/code/modules/maps/planet_types/grass.dm
+++ b/code/modules/maps/planet_types/grass.dm
@@ -8,8 +8,8 @@
surfacewater = "63% surface water, majority readings not visibly potable. Expected mineral toxicity or salt presence in water bodies"
planetary_area = /area/exoplanet/grass
rock_colors = list(COLOR_ASTEROID_ROCK, COLOR_GRAY80, COLOR_BROWN)
- plant_colors = list("#0e1e14","#1a3e38","#5a7467","#9eab88","#6e7248", "RANDOM")
- map_generators = list(/datum/random_map/noise/exoplanet/grass)
+ plant_colors = list("#3c772e","#27614b","#3f8d35","#185f18","#799628", "RANDOM")
+ possible_themes = list(/datum/exoplanet_theme/grass)
ruin_planet_type = PLANET_GRASS
ruin_allowed_tags = RUIN_LOWPOP|RUIN_SCIENCE|RUIN_HOSTILE|RUIN_WRECK|RUIN_NATURAL
@@ -46,21 +46,8 @@
if(prob(30))
S.set_trait(TRAIT_PARASITE,1)
-/area/exoplanet/grass
- base_turf = /turf/simulated/floor/exoplanet/grass
- ambience = list('sound/effects/wind/wind_2_1.ogg','sound/effects/wind/wind_2_2.ogg','sound/effects/wind/wind_3_1.ogg','sound/effects/wind/wind_4_1.ogg','sound/ambience/eeriejungle2.ogg','sound/ambience/eeriejungle1.ogg')
-
-/area/exoplanet/grass/play_ambience(var/mob/living/L)
- ..()
- if(L && L.client && (L.client.prefs.sfx_toggles & ASFX_AMBIENCE) && !L.ear_deaf)
- L.playsound_to(get_turf(L),sound('sound/ambience/jungle.ogg', repeat = 1, wait = 0, volume = 25, channel = 1))
-
-/datum/random_map/noise/exoplanet/grass
- descriptor = "grass exoplanet"
- smoothing_iterations = 2
- land_type = /turf/simulated/floor/exoplanet/grass
- water_type = /turf/simulated/floor/exoplanet/water/shallow
-
- flora_prob = 10
- flora_diversity = 6
- fauna_types = list(/mob/living/simple_animal/yithian, /mob/living/simple_animal/tindalos, /mob/living/simple_animal/cosmozoan)
+/obj/effect/overmap/visitable/sector/exoplanet/grass/marsh
+ name = "marsh exoplanet"
+ desc = "A swampy planet, home to exotic creatures and flora."
+ possible_themes = list(/datum/exoplanet_theme/grass/marsh)
+ ruin_planet_type = PLANET_MARSH
diff --git a/code/modules/maps/planet_types/jungle.dm b/code/modules/maps/planet_types/jungle.dm
index 9d94c1fbc5f..3c97c0941a6 100644
--- a/code/modules/maps/planet_types/jungle.dm
+++ b/code/modules/maps/planet_types/jungle.dm
@@ -7,47 +7,9 @@
rock_colors = list(COLOR_BEIGE, COLOR_PALE_YELLOW, COLOR_GRAY80, COLOR_BROWN)
grass_color = null
plant_colors = null
- map_generators = list(/datum/random_map/noise/exoplanet/grass/grove)
- possible_themes = list(/datum/exoplanet_theme/mountains/breathable)
+ possible_themes = list(/datum/exoplanet_theme/jungle)
ruin_planet_type = PLANET_GROVE
ruin_allowed_tags = RUIN_LOWPOP|RUIN_SCIENCE|RUIN_HOSTILE|RUIN_WRECK|RUIN_NATURAL
/obj/effect/overmap/visitable/sector/exoplanet/grass/grove/get_surface_color()
return "#5C7F34"
-
-/area/exoplanet/grass/grove
- base_turf = /turf/simulated/floor/exoplanet/grass/grove
-
-/datum/random_map/noise/exoplanet/grass/grove
- descriptor = "grove exoplanet"
- smoothing_iterations = 2
- land_type = /turf/simulated/floor/exoplanet/grass/grove
- water_type = /turf/simulated/floor/exoplanet/water/shallow
-
- fauna_prob = 1
- fauna_types = list(/mob/living/simple_animal/yithian, /mob/living/simple_animal/tindalos)
-
-/datum/random_map/noise/exoplanet/grass/grove/get_additional_spawns(var/value, var/turf/T)
- ..()
- if(istype(T, water_type))
- return
- if(T.density)
- return
- var/val = min(10,max(0,round((value/cell_range)*10)))
- if(isnull(val)) val = 0
- switch(val)
- if(2)
- if(prob(25))
- new /obj/structure/flora/bamboo(T)
- if(3)
- if(prob(25))
- new /obj/structure/flora/stalks(T)
- if(4)
- if(prob(75))
- new /obj/structure/flora/clutter(T)
- if(5)
- if(prob(35))
- new /obj/structure/flora/bush/grove(T)
- if(6)
- if(prob(25))
- new /obj/structure/flora/tree/grove(T)
diff --git a/code/modules/maps/planet_types/lava.dm b/code/modules/maps/planet_types/lava.dm
index 12f3ce0d28b..2f8f74a478f 100644
--- a/code/modules/maps/planet_types/lava.dm
+++ b/code/modules/maps/planet_types/lava.dm
@@ -6,10 +6,9 @@
geology = "Extreme, surface-apparent tectonic activity. Unreadable high-energy geothermal readings. Surface traversal demands caution"
weather = "Global sub-atmospheric volcanic ambient weather system. Exercise extreme caution with unpredictable volcanic eruption"
surfacewater = "Majority superheated methane, silicon and metallic substances, 7% liquid surface area."
- planetary_area = /area/exoplanet/barren
+ planetary_area = /area/exoplanet/lava
rock_colors = list(COLOR_DARK_GRAY)
- possible_themes = list(/datum/exoplanet_theme/mountains)
- map_generators = list(/datum/random_map/noise/exoplanet/lava, /datum/random_map/noise/ore)
+ possible_themes = list(/datum/exoplanet_theme/volcanic)
features_budget = 4
surface_color = "#cf1020"
water_color = null
@@ -25,19 +24,3 @@
/obj/effect/overmap/visitable/sector/exoplanet/lava/get_surface_color()
return "#575d5e"
-
-/datum/random_map/noise/exoplanet/lava
- descriptor = "lava exoplanet"
- smoothing_iterations = 4
- land_type = /turf/unsimulated/floor/asteroid/basalt
- water_type = /turf/simulated/lava
- water_level_min = 3
- water_level_max = 5
- flora_prob = 0
- flora_diversity = 0
- fauna_prob = 0
-
-/area/exoplanet/lava
- name = "\improper Planetary surface"
- ambience = AMBIENCE_LAVA
- base_turf = /turf/unsimulated/floor/asteroid/basalt
diff --git a/code/modules/maps/planet_types/lore/srandmarr.dm b/code/modules/maps/planet_types/lore/srandmarr.dm
index f9338be3f7e..abdb8cbd907 100644
--- a/code/modules/maps/planet_types/lore/srandmarr.dm
+++ b/code/modules/maps/planet_types/lore/srandmarr.dm
@@ -5,8 +5,6 @@
color = "#bf7c39"
icon_state = "globe1"
rock_colors = list(COLOR_GRAY80)
- possible_themes = list(/datum/exoplanet_theme/mountains)
- map_generators = list(/datum/random_map/noise/exoplanet/barren, /datum/random_map/noise/ore)
features_budget = 1
surface_color = "#B1A69B"
generated_name = FALSE
@@ -36,8 +34,6 @@
rock_colors = null
plant_colors = null
rock_colors = list("#4a3f41")
- possible_themes = list(/datum/exoplanet_theme/mountains)
- map_generators = list(/datum/random_map/noise/exoplanet/barren, /datum/random_map/noise/ore)
features_budget = 1
surface_color = "#4a3f41"
generated_name = FALSE
@@ -88,8 +84,7 @@
surfacegravity = "0.25"
charted = "Natural satellite of Tajaran homeworld, charted 2418CE, NanoTrasen Corporation"
geology = "Zero tectonic heat, completely dormant geothermal signature. Presumed dead core"
- possible_themes = list(/datum/exoplanet_theme/mountains)
- map_generators = list(/datum/random_map/noise/exoplanet/barren/raskara, /datum/random_map/noise/ore)
+ possible_themes = list(/datum/exoplanet_theme/barren/raskara)
features_budget = 1
surface_color = "#373737"
generated_name = FALSE
@@ -109,23 +104,6 @@
skybox_image.pixel_x = rand(0,64)
skybox_image.pixel_y = rand(128,256)
-/datum/random_map/noise/exoplanet/barren/raskara
- land_type = /turf/simulated/floor/exoplanet/barren/raskara
-
-/turf/simulated/floor/exoplanet/barren/raskara
- name = "ground"
- icon = 'icons/turf/flooring/asteroid.dmi'
- icon_state = "asteroid"
- color = "#373737"
-
-/turf/simulated/floor/exoplanet/barren/update_icon()
- overlays.Cut()
-
-/area/exoplanet/barren/raskara
- name = "Raskara Surface"
- ambience = AMBIENCE_OTHERWORLDLY
- base_turf = /turf/simulated/floor/exoplanet/barren/raskara
-
//Adhomai
/obj/effect/overmap/visitable/sector/exoplanet/adhomai
name = "Adhomai"
@@ -142,8 +120,7 @@
surfacewater = "Majority frozen, 78% surface water. Significant tidal forces from natural satellite"
rock_colors = null
plant_colors = null
- possible_themes = list(/datum/exoplanet_theme/mountains/adhomai)
- map_generators = list(/datum/random_map/noise/exoplanet/snow/adhomai, /datum/random_map/noise/ore/rich)
+ possible_themes = list(/datum/exoplanet_theme/snow/adhomai)
features_budget = 8
surface_color = "#e8faff"
water_color = "#b5dfeb"
@@ -187,7 +164,7 @@
if("North Pole")
features_budget = 1
- map_generators = list(/datum/random_map/noise/exoplanet/snow/adhomai_north_pole, /datum/random_map/noise/ore/rich)
+ possible_themes = list(/datum/exoplanet_theme/snow/tundra/adhomai)
ruin_type_whitelist = list (/datum/map_template/ruin/exoplanet/north_pole_monolith, /datum/map_template/ruin/exoplanet/north_pole_nka_expedition, /datum/map_template/ruin/exoplanet/north_pole_worm)
desc += " The landing sites are located at the [landing_faction]'s territory."
@@ -216,106 +193,3 @@
/obj/effect/overmap/visitable/sector/exoplanet/adhomai/update_icon()
return
-
-/datum/random_map/noise/exoplanet/snow/adhomai
- descriptor = "Adhomai"
- smoothing_iterations = 1
- flora_prob = 5
- water_level_max = 2
- land_type = /turf/simulated/floor/exoplanet/snow
- water_type = /turf/simulated/floor/exoplanet/ice
- fauna_types = list(/mob/living/simple_animal/ice_tunneler, /mob/living/simple_animal/ice_tunneler/male, /mob/living/simple_animal/fatshouter, /mob/living/simple_animal/fatshouter/male,
- /mob/living/simple_animal/hostile/retaliate/rafama, /mob/living/simple_animal/hostile/retaliate/rafama/male, /mob/living/simple_animal/hostile/retaliate/rafama/baby,
- /mob/living/simple_animal/hostile/wind_devil, /mob/living/carbon/human/farwa/adhomai, /mob/living/simple_animal/hostile/harron, /mob/living/simple_animal/climber,
- /mob/living/simple_animal/snow_strider, /mob/living/simple_animal/nosehorn)
-
-/datum/random_map/noise/exoplanet/snow/adhomai/generate_flora()
- for(var/i = 1 to flora_diversity)
- var/seed_chosen = pick("shand", "mtear", "earthenroot", "nifberries", "nfrihi", "nmshaan")
- var/datum/seed/chosen_seed = SSplants.seeds[seed_chosen]
-
- small_flora_types += chosen_seed
-
-/datum/random_map/noise/exoplanet/snow/adhomai/get_additional_spawns(var/value, var/turf/T)
- ..()
- if(istype(T, water_type))
- return
- if(T.density)
- return
- var/val = min(10,max(0,round((value/cell_range)*10)))
- if(isnull(val)) val = 0
- switch(val)
- if(2)
- if(prob(10))
- new /obj/structure/flora/rock/ice(T)
- if(3)
- if(prob(50))
- new /obj/structure/flora/grass/adhomai(T)
- if(4)
- if(prob(50))
- new /obj/structure/flora/bush/adhomai(T)
- if(5)
- if(prob(15))
- new /obj/structure/flora/tree/adhomai(T)
- if(6)
- if(prob(15))
- new /obj/structure/flora/rock/adhomai(T)
- if(7)
- if(prob(15))
- new /obj/effect/floor_decal/snowdrift(T)
- if(8)
- if(prob(10))
- new /obj/effect/floor_decal/snowdrift/large(T)
-
-/datum/random_map/noise/exoplanet/snow/adhomai_north_pole
- descriptor = "Adhomai North pole"
- smoothing_iterations = 1
- flora_prob = 0
- water_level_max = 4
- land_type = /turf/simulated/floor/exoplanet/snow
- water_type = /turf/simulated/floor/exoplanet/ice/dark
- fauna_types = list(/mob/living/simple_animal/scavenger, /mob/living/simple_animal/ice_catcher, /mob/living/simple_animal/hostile/plasmageist, /mob/living/simple_animal/hostile/wriggler)
-
-/datum/random_map/noise/exoplanet/snow/adhomai_north_pole/generate_flora()
- return
-
-/datum/random_map/noise/exoplanet/snow/adhomai_north_pole/get_additional_spawns(var/value, var/turf/T)
- ..()
- if(istype(T, water_type))
- return
- if(T.density)
- return
- var/val = min(10,max(0,round((value/cell_range)*10)))
- if(isnull(val)) val = 0
- switch(val)
- if(2)
- if(prob(25))
- new /obj/structure/flora/rock/ice(T)
- if(3)
- if(prob(10))
- new /obj/structure/geyser(T)
- if(4)
- if(prob(20))
- new /obj/structure/flora/rock/adhomai(T)
- if(5)
- if(prob(15))
- new /obj/effect/floor_decal/snowdrift(T)
- if(6)
- if(prob(10))
- new /obj/effect/floor_decal/snowdrift/large(T)
-
-/area/exoplanet/adhomai
- name = "Adhomian Wilderness"
- ambience = list('sound/effects/wind/tundra0.ogg', 'sound/effects/wind/tundra1.ogg', 'sound/effects/wind/tundra2.ogg', 'sound/effects/wind/spooky0.ogg', 'sound/effects/wind/spooky1.ogg')
- base_turf = /turf/simulated/floor/exoplanet/mineral/adhomai
-
-/turf/simulated/floor/exoplanet/mineral/adhomai
- name = "icy rock"
- icon = 'icons/turf/flooring/ice_cavern.dmi'
- icon_state = "icy_rock"
- temperature = T0C - 5
- has_edge_icon = FALSE
-
-/turf/simulated/floor/exoplanet/mineral/adhomai/Initialize(mapload)
- . = ..()
- icon_state = "icy_rock[rand(1,19)]"
diff --git a/code/modules/maps/planet_types/snow.dm b/code/modules/maps/planet_types/snow.dm
index e8c304e1709..49849df1d8c 100644
--- a/code/modules/maps/planet_types/snow.dm
+++ b/code/modules/maps/planet_types/snow.dm
@@ -9,7 +9,7 @@
planetary_area = /area/exoplanet/snow
rock_colors = list(COLOR_DARK_BLUE_GRAY, COLOR_GUNMETAL, COLOR_GRAY80, COLOR_DARK_GRAY)
plant_colors = list("#d0fef5","#93e1d8","#93e1d8", "#b2abbf", "#3590f3", "#4b4e6d")
- map_generators = list(/datum/random_map/noise/exoplanet/snow)
+ possible_themes = list(/datum/exoplanet_theme/snow)
surface_color = "#e8faff"
water_color = "#b5dfeb"
@@ -22,16 +22,3 @@
limit = initial(H.cold_level_1) + rand(1,10)
atmosphere.temperature = max(T0C - rand(10, 100), limit)
atmosphere.update_values()
-
-/datum/random_map/noise/exoplanet/snow
- descriptor = "snow exoplanet"
- smoothing_iterations = 1
- flora_prob = 5
- water_level_max = 3
- land_type = /turf/simulated/floor/exoplanet/snow
- water_type = /turf/simulated/floor/exoplanet/ice
- fauna_types = list(/mob/living/simple_animal/hostile/retaliate/samak, /mob/living/simple_animal/hostile/retaliate/diyaab, /mob/living/simple_animal/hostile/retaliate/shantak)
-
-/area/exoplanet/snow
- ambience = list('sound/effects/wind/tundra0.ogg','sound/effects/wind/tundra1.ogg','sound/effects/wind/tundra2.ogg','sound/effects/wind/spooky0.ogg','sound/effects/wind/spooky1.ogg')
- base_turf = /turf/simulated/floor/exoplanet/snow
diff --git a/code/modules/maps/reader.dm b/code/modules/maps/reader.dm
index 0b52454d0fc..924199d3c2f 100644
--- a/code/modules/maps/reader.dm
+++ b/code/modules/maps/reader.dm
@@ -372,7 +372,7 @@ var/global/dmm_suite/preloader/_preloader = new
if(crds)
if(!no_changeturf && ispath(path, /turf))
- . = crds.ChangeTurf(path, FALSE, TRUE)
+ . = crds.ChangeTurf(path, FALSE, TRUE, TRUE)
else
. = create_atom(path, crds)//first preloader pass
diff --git a/code/modules/maps/ruins.dm b/code/modules/maps/ruins.dm
index ea319b5aa7e..01eaee5f6cc 100644
--- a/code/modules/maps/ruins.dm
+++ b/code/modules/maps/ruins.dm
@@ -106,6 +106,9 @@ var/list/banned_ruin_ids = list()
qdel(S)
for(var/obj/machinery/M in T)
qdel(M)
+ if(LAZYLEN(T.decals))
+ T.decals.Cut()
+ T.cut_overlays()
template.load(central_turf, TRUE)
var/datum/map_template/ruin = template
if(istype(ruin))
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 38f0fc732f9..c20a2bba6bb 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -15,7 +15,6 @@ var/list/mineral_can_smooth_with = list(
/turf/unsimulated/wall
)
-
/turf/simulated/mineral //wall piece
name = "rock"
icon = 'icons/turf/map_placeholders.dmi'
@@ -83,10 +82,6 @@ var/list/mineral_can_smooth_with = list(
canSmoothWith = mineral_can_smooth_with
pixel_x = -4
pixel_y = -4
- queue_smooth(src)
-
- if(!mapload)
- queue_smooth_neighbors(src)
rock_health = rand(10,20)
@@ -96,11 +91,6 @@ var/list/mineral_can_smooth_with = list(
// Hard-coding this for performance reasons.
baseturf = A.base_turf || current_map.base_turf_by_z["[z]"] || /turf/space
- if (current_map.use_overmap && istype(A, /area/exoplanet))
- var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
- if (istype(E) && istype(E.theme))
- E.theme.on_turf_generation(src, E.planetary_area)
-
return INITIALIZE_HINT_NORMAL
/turf/simulated/mineral/examine(mob/user)
@@ -210,15 +200,6 @@ var/list/mineral_can_smooth_with = list(
canSmoothWith = asteroid_can_smooth_with
pixel_x = -4
pixel_y = -4
- queue_smooth(src)
-
- if(!mapload)
- queue_smooth_neighbors(src)
-
- if (current_map.use_overmap && istype(loc, /area/exoplanet))
- var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
- if (istype(E) && istype(E.theme))
- E.theme.on_turf_generation(src, E.planetary_area)
return INITIALIZE_HINT_NORMAL
@@ -486,6 +467,13 @@ var/list/mineral_can_smooth_with = list(
var/obj/item/stack/material/uranium/R = new(src)
R.amount = rand(5, 25)
+/turf/simulated/mineral/proc/change_mineral(mineral_name, force = FALSE)
+ if(mineral_name && (mineral_name in ore_data))
+ if(mineral && !force)
+ return FALSE
+ mineral = ore_data[mineral_name]
+ UpdateMineral()
+
/turf/simulated/mineral/random
name = "mineral deposit"
var/mineralSpawnChanceList = list(
@@ -669,19 +657,10 @@ var/list/asteroid_floor_smooth = list(
canSmoothWith = asteroid_floor_smooth
pixel_x = -4
pixel_y = -4
- queue_smooth(src)
-
- if(!mapload)
- queue_smooth_neighbors(src)
if(light_range && light_power)
update_light()
- if (current_map.use_overmap && istype(loc, /area/exoplanet))
- var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
- if (istype(E) && istype(E.theme))
- E.theme.on_turf_generation(src, E.planetary_area)
-
return INITIALIZE_HINT_NORMAL
/turf/unsimulated/floor/asteroid/ex_act(severity)
diff --git a/code/modules/mob/abstract/freelook/update_triggers.dm b/code/modules/mob/abstract/freelook/update_triggers.dm
index ead7f53fef6..08862828030 100644
--- a/code/modules/mob/abstract/freelook/update_triggers.dm
+++ b/code/modules/mob/abstract/freelook/update_triggers.dm
@@ -25,7 +25,7 @@
if(opacity && .)
updateVisibility(src)
-/turf/ChangeTurf()
+/turf/ChangeTurf(N, tell_universe = TRUE, force_lighting_update = FALSE, ignore_override = FALSE, mapload = FALSE)
. = ..()
if(.)
updateVisibility(src, FALSE)
diff --git a/code/modules/overmap/exoplanets/_defines/planetgen.dm b/code/modules/overmap/exoplanets/_defines/planetgen.dm
new file mode 100644
index 00000000000..1f2b77970fd
--- /dev/null
+++ b/code/modules/overmap/exoplanets/_defines/planetgen.dm
@@ -0,0 +1,39 @@
+#define BIOME_RANDOM_SQUARE_DRIFT 2
+
+#define BIOME_POLAR "polar"
+#define BIOME_COOL "cool"
+#define BIOME_WARM "warm"
+#define BIOME_EQUATOR "equatorial"
+
+#define BIOME_ARID "arid"
+#define BIOME_SEMIARID "semiarid"
+#define BIOME_SUBHUMID "subhumid"
+#define BIOME_HUMID "humid"
+
+/// Discrete batched perlin-like noise; results in large clumps, argument is cutoff value (lower value makes spawns rarer), range (-0.5, 0.5)
+#define BATCHED_NOISE BITFLAG(0)
+/// Poisson disk sampling; results in a uniform distribution of single points, argument is minimum # turfs between points
+#define POISSON_SAMPLE BITFLAG(1)
+/// Pure random chance on a per-tile basis; equivalent to prob(X) per turf
+#define PURE_RANDOM BITFLAG(2)
+/// Will always spawn terrain features of this type
+#define ALWAYS_GEN BITFLAG(3)
+/// ALWAYS_GEN but only in the lower 0.0-0.99x bound specified for normal heat/humidity in this biome
+#define HEIGHT_MOD BITFLAG(4)
+
+/// The only 'mandatory' generator define, insofar that you need to use it to override turf_type
+#define PLANET_TURF "turfs"
+// Some useful defines, but so long as generators and spawn_turfs have the same string value,
+// these can be literally anything
+#define GRASSES "grasses"
+#define SMALL_FLORA "bushes"
+#define LARGE_FLORA "trees"
+#define WILDLIFE "mobs"
+
+#define GRASS_1 "grass1"
+#define GRASS_2 "grass2"
+#define GRASS_3 "grass3"
+
+#define SURFACE_ORES "surface"
+#define RARE_ORES "rare"
+#define DEEP_ORES "deep" // yo that's deep
diff --git a/code/modules/overmap/exoplanets/biomes/_biome.dm b/code/modules/overmap/exoplanets/biomes/_biome.dm
new file mode 100644
index 00000000000..f4b41904405
--- /dev/null
+++ b/code/modules/overmap/exoplanets/biomes/_biome.dm
@@ -0,0 +1,18 @@
+/singleton/biome
+ /// Fallback turf if no PLANET_TURF generator is specified, which is true in most cases
+ var/turf_type
+ var/list/generators = list()
+ var/list/spawn_types = list()
+ var/list/exclusive_generators = list(LARGE_FLORA)
+
+/singleton/biome/mountain
+ turf_type = /turf/simulated/mineral
+
+/singleton/biome/mountain/adhomai
+ turf_type = /turf/simulated/mineral/adhomai
+
+/singleton/biome/water
+ turf_type = /turf/simulated/floor/exoplanet/water/shallow
+
+/singleton/biome/water/ice
+ turf_type = /turf/simulated/floor/exoplanet/ice
diff --git a/code/modules/overmap/exoplanets/biomes/barren.dm b/code/modules/overmap/exoplanets/biomes/barren.dm
new file mode 100644
index 00000000000..fb9e3a76f2d
--- /dev/null
+++ b/code/modules/overmap/exoplanets/biomes/barren.dm
@@ -0,0 +1,22 @@
+/singleton/biome/barren
+ turf_type = /turf/simulated/floor/exoplanet/barren
+ generators = list(
+ WILDLIFE = list(POISSON_SAMPLE, 15)
+ )
+ spawn_types = list(
+ WILDLIFE = list(
+ /mob/living/simple_animal/hostile/gnat = 5,
+ /mob/living/simple_animal/hostile/carp/asteroid = 3,
+ /mob/living/simple_animal/hostile/carp/bloater = 1,
+ /mob/living/simple_animal/hostile/carp/shark/reaver = 1,
+ /mob/living/simple_animal/hostile/carp/shark/reaver/eel = 1
+ )
+ )
+
+/singleton/biome/barren/asteroid
+ turf_type = /turf/unsimulated/floor/asteroid/ash
+
+/singleton/biome/barren/raskara
+ turf_type = /turf/simulated/floor/exoplanet/barren/raskara
+ generators = list()
+ spawn_types = list()
diff --git a/code/modules/overmap/exoplanets/biomes/crystal.dm b/code/modules/overmap/exoplanets/biomes/crystal.dm
new file mode 100644
index 00000000000..756609f4164
--- /dev/null
+++ b/code/modules/overmap/exoplanets/biomes/crystal.dm
@@ -0,0 +1,19 @@
+/singleton/biome/crystal
+ turf_type = /turf/simulated/floor/exoplanet/crystal
+ generators = list(
+ GRASSES = list(BATCHED_NOISE, -0.1, 360, 16),
+ LARGE_FLORA = list(POISSON_SAMPLE, 12),
+ WILDLIFE = list(POISSON_SAMPLE, 12)
+ )
+ spawn_types = list(
+ GRASSES = list(
+ /obj/effect/floor_decal/crystal/random = 1
+ ),
+ LARGE_FLORA = list(
+ /obj/structure/flora/rock/spire = 1,
+ /obj/structure/flora/tree/crystal = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/cosmozoan = 1
+ )
+ )
diff --git a/code/modules/overmap/exoplanets/biomes/desert.dm b/code/modules/overmap/exoplanets/biomes/desert.dm
new file mode 100644
index 00000000000..1a2508bcc63
--- /dev/null
+++ b/code/modules/overmap/exoplanets/biomes/desert.dm
@@ -0,0 +1,74 @@
+/singleton/biome/desert
+ turf_type = /turf/simulated/floor/exoplanet/desert
+ generators = list(
+ SMALL_FLORA = list(POISSON_SAMPLE, 7),
+ LARGE_FLORA = list(POISSON_SAMPLE, 7),
+ WILDLIFE = list(POISSON_SAMPLE, 25)
+ )
+ spawn_types = list(
+ SMALL_FLORA = list(
+ /obj/structure/flora/rock/desert = 3,
+ /obj/structure/flora/rock/desert/scrub = 2
+ ),
+ LARGE_FLORA = list(
+ /obj/effect/floor_decal/dune/random = 3,
+ /obj/structure/flora/tree/desert/tiny = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/thinbug = 2,
+ /mob/living/simple_animal/tindalos = 1
+ )
+ )
+
+/singleton/biome/desert/scrub
+ generators = list(
+ GRASSES = list(BATCHED_NOISE, -0.1, 360, 4),
+ SMALL_FLORA = list(POISSON_SAMPLE, 4),
+ LARGE_FLORA = list(POISSON_SAMPLE, 7),
+ WILDLIFE = list(POISSON_SAMPLE, 15)
+ )
+ spawn_types = list(
+ GRASSES = list(
+ /obj/structure/flora/grass/desert/bush = 1,
+ /obj/structure/flora/grass/desert = 3
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/rock/desert = 1,
+ /obj/structure/flora/rock/desert/scrub = 3,
+ ),
+ LARGE_FLORA = list(
+ /obj/structure/flora/tree/desert/tiny = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/thinbug = 2,
+ /mob/living/simple_animal/tindalos = 1
+ )
+ )
+
+/singleton/biome/desert/thorn
+ turf_type = /turf/simulated/floor/exoplanet/desert/rough
+ generators = list(
+ GRASSES = list(ALWAYS_GEN),
+ SMALL_FLORA = list(POISSON_SAMPLE, 8),
+ LARGE_FLORA = list(POISSON_SAMPLE, 4),
+ WILDLIFE = list(POISSON_SAMPLE, 10)
+ )
+ spawn_types = list(
+ GRASSES = list(
+ /obj/structure/flora/grass/desert/bush = 3,
+ /obj/structure/flora/grass/desert = 2
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/rock/desert = 1,
+ /obj/structure/flora/rock/desert/scrub = 1,
+ ),
+ LARGE_FLORA = list(
+ /obj/structure/flora/tree/desert/tiny = 4,
+ /obj/structure/flora/tree/desert/small = 2,
+ /obj/structure/flora/tree/desert = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/thinbug = 2,
+ /mob/living/simple_animal/tindalos = 1
+ )
+ )
diff --git a/code/modules/overmap/exoplanets/biomes/grass.dm b/code/modules/overmap/exoplanets/biomes/grass.dm
new file mode 100644
index 00000000000..b50277bbd59
--- /dev/null
+++ b/code/modules/overmap/exoplanets/biomes/grass.dm
@@ -0,0 +1,116 @@
+/singleton/biome/grass
+ turf_type = /turf/simulated/floor/exoplanet/grass/stalk
+ generators = list(
+ GRASS_1 = list(BATCHED_NOISE, -0.3, 360, 4),
+ GRASS_2 = list(BATCHED_NOISE, -0.3, 360, 4),
+ GRASS_3 = list(BATCHED_NOISE, -0.3, 360, 4),
+ SMALL_FLORA = list(POISSON_SAMPLE, 6),
+ WILDLIFE = list(POISSON_SAMPLE, 15)
+ )
+ exclusive_generators = list(GRASS_1, GRASS_2, GRASS_3)
+ spawn_types = list(
+ GRASS_1 = list(
+ /obj/structure/flora/ausbushes/ywflowers = 1
+ ),
+ GRASS_2 = list(
+ /obj/structure/flora/ausbushes/brflowers = 1
+ ),
+ GRASS_3 = list(
+ /obj/structure/flora/ausbushes/ppflowers = 1
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/ausbushes/ywflowers = 1,
+ /obj/structure/flora/ausbushes/brflowers = 1,
+ /obj/structure/flora/ausbushes/ppflowers = 1,
+ /obj/structure/flora/ausbushes/grassybush = 1,
+ /obj/structure/flora/ausbushes/palebush = 1,
+ /obj/structure/flora/ausbushes = 1,
+ /obj/structure/flora/ausbushes/fernybush = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/yithian = 2,
+ /mob/living/simple_animal/tindalos = 2,
+ /mob/living/simple_animal/cosmozoan = 1,
+ )
+ )
+
+/singleton/biome/grass/riverside
+ generators = list(
+ PLANET_TURF = list(HEIGHT_MOD, 0.95),
+ SMALL_FLORA = list(POISSON_SAMPLE, 1),
+ WILDLIFE = list(POISSON_SAMPLE, 15)
+ )
+ exclusive_generators = list(PLANET_TURF)
+ spawn_types = list(
+ PLANET_TURF = list(
+ /turf/simulated/floor/exoplanet/water/shallow = 1
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/ausbushes/reedbush = 1,
+ /obj/structure/flora/ausbushes/stalkybush = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/yithian = 2,
+ /mob/living/simple_animal/tindalos = 2,
+ /mob/living/simple_animal/cosmozoan = 1,
+ )
+ )
+
+/singleton/biome/grass/chaparral
+ generators = list(
+ GRASS_1 = list(BATCHED_NOISE, -0.4, 360, 4),
+ GRASS_2 = list(BATCHED_NOISE, -0.4, 360, 4),
+ GRASS_3 = list(BATCHED_NOISE, -0.4, 360, 4),
+ SMALL_FLORA = list(POISSON_SAMPLE, 3),
+ WILDLIFE = list(POISSON_SAMPLE, 15)
+ )
+ exclusive_generators = list(GRASS_1, GRASS_2, GRASS_3)
+ spawn_types = list(
+ GRASS_1 = list(
+ /obj/structure/flora/ausbushes/ywflowers = 1
+ ),
+ GRASS_2 = list(
+ /obj/structure/flora/ausbushes/brflowers = 1
+ ),
+ GRASS_3 = list(
+ /obj/structure/flora/ausbushes/ppflowers = 1
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/ausbushes/grassybush = 1,
+ /obj/structure/flora/ausbushes/palebush = 1,
+ /obj/structure/flora/ausbushes = 1,
+ /obj/structure/flora/ausbushes/fernybush = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/yithian = 2,
+ /mob/living/simple_animal/tindalos = 2,
+ /mob/living/simple_animal/cosmozoan = 1,
+ )
+ )
+
+/singleton/biome/grass/forest
+ generators = list(
+ LARGE_FLORA = list(POISSON_SAMPLE, 5),
+ SMALL_FLORA = list(POISSON_SAMPLE, 1),
+ WILDLIFE = list(POISSON_SAMPLE, 15)
+ )
+ exclusive_generators = list(LARGE_FLORA)
+ spawn_types = list(
+ LARGE_FLORA = list(
+ /obj/structure/flora/tree/grove = 1
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/ausbushes/ywflowers = 1,
+ /obj/structure/flora/ausbushes/brflowers = 1,
+ /obj/structure/flora/ausbushes/ppflowers = 1,
+ /obj/structure/flora/ausbushes/grassybush = 1,
+ /obj/structure/flora/ausbushes/palebush = 1,
+ /obj/structure/flora/ausbushes = 1,
+ /obj/structure/flora/ausbushes/fernybush = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/yithian = 2,
+ /mob/living/simple_animal/tindalos = 2,
+ /mob/living/simple_animal/cosmozoan = 1,
+ )
+ )
diff --git a/code/modules/overmap/exoplanets/biomes/jungle.dm b/code/modules/overmap/exoplanets/biomes/jungle.dm
new file mode 100644
index 00000000000..61414334add
--- /dev/null
+++ b/code/modules/overmap/exoplanets/biomes/jungle.dm
@@ -0,0 +1,62 @@
+/singleton/biome/jungle
+ turf_type = /turf/simulated/floor/exoplanet/grass/grove
+ generators = list(
+ LARGE_FLORA = list(POISSON_SAMPLE, 7),
+ SMALL_FLORA = list(POISSON_SAMPLE, 4),
+ GRASSES = list(BATCHED_NOISE, 0.1, 360, 4),
+ WILDLIFE = list(POISSON_SAMPLE, 10)
+ )
+ spawn_types = list(
+ LARGE_FLORA = list(
+ /obj/structure/flora/tree/jungle/small/random = 5,
+ /obj/structure/flora/tree/jungle/random = 1
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/bush/jungle/large/random = 1,
+ /obj/structure/flora/bush/jungle/random = 3,
+ /obj/structure/flora/bush/jungle/b/random = 3,
+ /obj/structure/flora/bush/jungle/c/random = 3
+ ),
+ GRASSES = list(
+ /obj/effect/floor_decal/junglegrass/random = 4,
+ /obj/effect/floor_decal/junglegrass/dense/random = 2,
+ /obj/effect/floor_decal/junglegrass/rocky/random = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/yithian = 1,
+ /mob/living/simple_animal/tindalos = 1
+ )
+ )
+ exclusive_generators = list(LARGE_FLORA, SMALL_FLORA)
+
+/singleton/biome/jungle/clearing
+ // same as /jungle but without any blocking objs
+ generators = list(
+ SMALL_FLORA = list(POISSON_SAMPLE, 4),
+ GRASSES = list(BATCHED_NOISE, -0.1, 360, 4),
+ WILDLIFE = list(POISSON_SAMPLE, 10)
+ )
+ spawn_types = list(
+ SMALL_FLORA = list(
+ /obj/structure/flora/bush/jungle/random = 3,
+ /obj/structure/flora/bush/jungle/b/random = 3,
+ /obj/structure/flora/bush/jungle/c/random = 3
+ ),
+ GRASSES = list(
+ /obj/effect/floor_decal/junglegrass/random = 4,
+ /obj/effect/floor_decal/junglegrass/dense/random = 2,
+ /obj/effect/floor_decal/junglegrass/rocky/random = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/yithian = 1,
+ /mob/living/simple_animal/tindalos = 1
+ )
+ )
+
+/singleton/biome/jungle/dense
+ generators = list(
+ LARGE_FLORA = list(POISSON_SAMPLE, 4),
+ SMALL_FLORA = list(POISSON_SAMPLE, 2),
+ GRASSES = list(ALWAYS_GEN),
+ WILDLIFE = list(POISSON_SAMPLE, 10)
+ )
diff --git a/code/modules/overmap/exoplanets/biomes/lava.dm b/code/modules/overmap/exoplanets/biomes/lava.dm
new file mode 100644
index 00000000000..e2463b8aadb
--- /dev/null
+++ b/code/modules/overmap/exoplanets/biomes/lava.dm
@@ -0,0 +1,27 @@
+/singleton/biome/lava
+ turf_type = /turf/simulated/lava
+
+/singleton/biome/barren/asteroid/basalt
+ turf_type = /turf/unsimulated/floor/asteroid/basalt
+ generators = list(
+ PLANET_TURF = list(BATCHED_NOISE, -0.1, 360, 32),
+ SMALL_FLORA = list(POISSON_SAMPLE, 9),
+ WILDLIFE = list(POISSON_SAMPLE, 15)
+ )
+ exclusive_generators = list(PLANET_TURF)
+ spawn_types = list(
+ PLANET_TURF = list(
+ /turf/simulated/lava = 1
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/rock/random = 1,
+ /obj/structure/flora/rock/pile/random = 2
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/hostile/gnat = 5,
+ /mob/living/simple_animal/hostile/carp/asteroid = 3,
+ /mob/living/simple_animal/hostile/carp/bloater = 1,
+ /mob/living/simple_animal/hostile/carp/shark/reaver = 1,
+ /mob/living/simple_animal/hostile/carp/shark/reaver/eel = 1
+ )
+ )
diff --git a/code/modules/overmap/exoplanets/biomes/marsh.dm b/code/modules/overmap/exoplanets/biomes/marsh.dm
new file mode 100644
index 00000000000..ab937df1a4c
--- /dev/null
+++ b/code/modules/overmap/exoplanets/biomes/marsh.dm
@@ -0,0 +1,33 @@
+/singleton/biome/marsh
+ turf_type = /turf/simulated/floor/exoplanet/grass/marsh
+ generators = list(
+ LARGE_FLORA = list(POISSON_SAMPLE, 15),
+ GRASSES = list(BATCHED_NOISE, -0.1, 360, 16),
+ SMALL_FLORA = list(POISSON_SAMPLE, 6),
+ WILDLIFE = list(POISSON_SAMPLE, 15)
+ )
+ exclusive_generators = list(LARGE_FLORA)
+ spawn_types = list(
+ LARGE_FLORA = list(
+ /obj/structure/flora/tree/mushroom = 1
+ ),
+ GRASSES = list(
+ /obj/effect/floor_decal/fungus/random = 1
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/bush/mushroom = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/yithian = 1,
+ /mob/living/simple_animal/tindalos = 1,
+ /mob/living/simple_animal/cosmozoan = 3,
+ )
+ )
+
+/singleton/biome/marsh/forest
+ generators = list(
+ LARGE_FLORA = list(POISSON_SAMPLE, 4),
+ GRASSES = list(BATCHED_NOISE, -0.3, 360, 16),
+ SMALL_FLORA = list(POISSON_SAMPLE, 2),
+ WILDLIFE = list(POISSON_SAMPLE, 10)
+ )
diff --git a/code/modules/overmap/exoplanets/biomes/snow.dm b/code/modules/overmap/exoplanets/biomes/snow.dm
new file mode 100644
index 00000000000..94d85b1c463
--- /dev/null
+++ b/code/modules/overmap/exoplanets/biomes/snow.dm
@@ -0,0 +1,157 @@
+/singleton/biome/snow
+ turf_type = /turf/simulated/floor/exoplanet/snow
+ generators = list(
+ PLANET_TURF = list(BATCHED_NOISE, -0.2, 360, 16),
+ GRASSES = list(BATCHED_NOISE, -0.4, 360, 4),
+ LARGE_FLORA = list(POISSON_SAMPLE, 9),
+ SMALL_FLORA = list(POISSON_SAMPLE, 6),
+ WILDLIFE = list(POISSON_SAMPLE, 15)
+ )
+ spawn_types = list(
+ PLANET_TURF = list(/turf/simulated/floor/exoplanet/permafrost = 1),
+ GRASSES = list(
+ /obj/structure/flora/grass/both = 2,
+ /obj/structure/flora/grass/green = 1,
+ /obj/structure/flora/grass/brown = 1
+ ),
+ LARGE_FLORA = list(
+ /obj/effect/floor_decal/snowdrift/large/random = 4,
+ /obj/structure/flora/rock/snow = 4,
+ /obj/structure/flora/tree/dead = 2,
+ /obj/structure/flora/tree/pine = 1
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/bush = 2,
+ /obj/effect/floor_decal/snowrocks = 1,
+ /obj/effect/floor_decal/snowdrift/random = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/hostile/retaliate/samak = 1,
+ /mob/living/simple_animal/hostile/retaliate/diyaab = 1,
+ /mob/living/simple_animal/hostile/retaliate/shantak = 1
+ )
+ )
+ exclusive_generators = list(LARGE_FLORA)
+
+/singleton/biome/snow/forest
+ generators = list(
+ GRASSES = list(BATCHED_NOISE, -0.4, 360, 4),
+ LARGE_FLORA = list(POISSON_SAMPLE, 4),
+ SMALL_FLORA = list(POISSON_SAMPLE, 2),
+ WILDLIFE = list(POISSON_SAMPLE, 8)
+ )
+ spawn_types = list(
+ GRASSES = list(
+ /obj/structure/flora/grass/both = 1,
+ /obj/structure/flora/grass/green = 2,
+ /obj/structure/flora/grass/brown = 1
+ ),
+ LARGE_FLORA = list(
+ /obj/structure/flora/rock/snow = 1,
+ /obj/structure/flora/tree/dead = 2,
+ /obj/structure/flora/tree/pine = 4
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/bush = 3,
+ /obj/effect/floor_decal/snowrocks = 1,
+ /obj/effect/floor_decal/snowdrift/random = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/hostile/retaliate/samak = 1,
+ /mob/living/simple_animal/hostile/retaliate/diyaab = 1,
+ /mob/living/simple_animal/hostile/retaliate/shantak = 1
+ )
+ )
+
+// Adhomai
+
+/singleton/biome/snow/adhomai
+ spawn_types = list(
+ PLANET_TURF = list(/turf/simulated/floor/exoplanet/permafrost = 1),
+ GRASSES = list(
+ /obj/structure/flora/grass/adhomai = 1
+ ),
+ LARGE_FLORA = list(
+ /obj/effect/floor_decal/snowdrift/large/random = 1,
+ /obj/structure/flora/rock/adhomai = 1,
+ /obj/structure/flora/tree/adhomai = 1
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/bush/adhomai = 3,
+ /obj/effect/floor_decal/snowdrift/random = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/ice_tunneler = 1,
+ /mob/living/simple_animal/ice_tunneler/male = 1,
+ /mob/living/simple_animal/fatshouter = 1,
+ /mob/living/simple_animal/fatshouter/male = 1,
+ /mob/living/simple_animal/hostile/retaliate/rafama = 1,
+ /mob/living/simple_animal/hostile/retaliate/rafama/male = 1,
+ /mob/living/simple_animal/hostile/retaliate/rafama/baby = 1,
+ /mob/living/simple_animal/hostile/wind_devil = 1,
+ /mob/living/carbon/human/farwa/adhomai = 1,
+ /mob/living/simple_animal/hostile/harron = 1,
+ /mob/living/simple_animal/climber = 1,
+ /mob/living/simple_animal/snow_strider = 1,
+ /mob/living/simple_animal/nosehorn = 1
+ )
+ )
+
+/singleton/biome/snow/forest/adhomai
+ spawn_types = list(
+ GRASSES = list(
+ /obj/structure/flora/grass/adhomai = 1
+ ),
+ LARGE_FLORA = list(
+ /obj/effect/floor_decal/snowdrift/large/random = 1,
+ /obj/structure/flora/rock/adhomai = 1,
+ /obj/structure/flora/tree/adhomai = 4
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/flora/bush/adhomai = 3,
+ /obj/effect/floor_decal/snowdrift/random = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/ice_tunneler = 1,
+ /mob/living/simple_animal/ice_tunneler/male = 1,
+ /mob/living/simple_animal/fatshouter = 1,
+ /mob/living/simple_animal/fatshouter/male = 1,
+ /mob/living/simple_animal/hostile/retaliate/rafama = 1,
+ /mob/living/simple_animal/hostile/retaliate/rafama/male = 1,
+ /mob/living/simple_animal/hostile/retaliate/rafama/baby = 1,
+ /mob/living/simple_animal/hostile/wind_devil = 1,
+ /mob/living/carbon/human/farwa/adhomai = 1,
+ /mob/living/simple_animal/hostile/harron = 1,
+ /mob/living/simple_animal/climber = 1,
+ /mob/living/simple_animal/snow_strider = 1,
+ /mob/living/simple_animal/nosehorn = 1
+ )
+ )
+
+/singleton/biome/snow/adhomai/polar
+ turf_type = /turf/simulated/floor/exoplanet/snow
+ generators = list(
+ LARGE_FLORA = list(POISSON_SAMPLE, 9),
+ SMALL_FLORA = list(POISSON_SAMPLE, 9),
+ WILDLIFE = list(POISSON_SAMPLE, 15)
+ )
+ spawn_types = list(
+ LARGE_FLORA = list(
+ /obj/effect/floor_decal/snowdrift/large/random = 1,
+ /obj/structure/flora/rock/adhomai = 2,
+ /obj/structure/flora/rock/ice = 3
+ ),
+ SMALL_FLORA = list(
+ /obj/structure/geyser = 1,
+ /obj/effect/floor_decal/snowdrift/random = 1
+ ),
+ WILDLIFE = list(
+ /mob/living/simple_animal/scavenger = 1,
+ /mob/living/simple_animal/ice_catcher = 1,
+ /mob/living/simple_animal/hostile/plasmageist = 1,
+ /mob/living/simple_animal/hostile/wriggler = 1
+ )
+ )
+
+/singleton/biome/water/ice/polar
+ turf_type = /turf/simulated/floor/exoplanet/ice/dark
diff --git a/code/modules/overmap/exoplanets/decor/_areas.dm b/code/modules/overmap/exoplanets/decor/_areas.dm
new file mode 100644
index 00000000000..cccddf65756
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/_areas.dm
@@ -0,0 +1,53 @@
+/area/exoplanet
+ name = "\improper Planetary surface"
+ ambience = list('sound/effects/wind/wind_2_1.ogg','sound/effects/wind/wind_2_2.ogg','sound/effects/wind/wind_3_1.ogg','sound/effects/wind/wind_4_1.ogg','sound/effects/wind/wind_4_2.ogg','sound/effects/wind/wind_5_1.ogg')
+ always_unpowered = 1
+
+/area/exoplanet/adhomai
+ name = "Adhomian Wilderness"
+ ambience = list('sound/effects/wind/tundra0.ogg', 'sound/effects/wind/tundra1.ogg', 'sound/effects/wind/tundra2.ogg', 'sound/effects/wind/spooky0.ogg', 'sound/effects/wind/spooky1.ogg')
+ base_turf = /turf/simulated/floor/exoplanet/mineral/adhomai
+
+/area/exoplanet/barren
+ name = "\improper Planetary surface"
+ ambience = list('sound/effects/wind/wind_2_1.ogg','sound/effects/wind/wind_2_2.ogg','sound/effects/wind/wind_3_1.ogg','sound/effects/wind/wind_4_1.ogg','sound/effects/wind/wind_4_2.ogg','sound/effects/wind/wind_5_1.ogg')
+ base_turf = /turf/simulated/floor/exoplanet/barren
+
+/area/exoplanet/barren/asteroid
+ name = "\improper Asteroid Surface"
+ base_turf = /turf/unsimulated/floor/asteroid/ash
+
+/area/exoplanet/barren/raskara
+ name = "Raskara Surface"
+ ambience = AMBIENCE_OTHERWORLDLY
+ base_turf = /turf/simulated/floor/exoplanet/barren/raskara
+
+/area/exoplanet/crystal
+ name = "\improper Planetary surface"
+ ambience = AMBIENCE_SPACE
+ base_turf = /turf/simulated/floor/exoplanet/crystal
+
+/area/exoplanet/desert
+ ambience = list('sound/effects/wind/desert0.ogg','sound/effects/wind/desert1.ogg','sound/effects/wind/desert2.ogg','sound/effects/wind/desert3.ogg','sound/effects/wind/desert4.ogg','sound/effects/wind/desert5.ogg')
+ base_turf = /turf/simulated/floor/exoplanet/desert
+
+/area/exoplanet/grass
+ base_turf = /turf/simulated/floor/exoplanet/grass
+ ambience = list('sound/effects/wind/wind_2_1.ogg','sound/effects/wind/wind_2_2.ogg','sound/effects/wind/wind_3_1.ogg','sound/effects/wind/wind_4_1.ogg','sound/ambience/eeriejungle2.ogg','sound/ambience/eeriejungle1.ogg')
+
+/area/exoplanet/grass/play_ambience(var/mob/living/L)
+ ..()
+ if(L && L.client && (L.client.prefs.sfx_toggles & ASFX_AMBIENCE) && !L.ear_deaf)
+ L.playsound_to(get_turf(L),sound('sound/ambience/jungle.ogg', repeat = 1, wait = 0, volume = 25, channel = 1))
+
+/area/exoplanet/grass/grove
+ base_turf = /turf/simulated/floor/exoplanet/grass/grove
+
+/area/exoplanet/lava
+ name = "\improper Planetary surface"
+ ambience = AMBIENCE_LAVA
+ base_turf = /turf/unsimulated/floor/asteroid/basalt
+
+/area/exoplanet/snow
+ ambience = list('sound/effects/wind/tundra0.ogg','sound/effects/wind/tundra1.ogg','sound/effects/wind/tundra2.ogg','sound/effects/wind/spooky0.ogg','sound/effects/wind/spooky1.ogg')
+ base_turf = /turf/simulated/floor/exoplanet/snow
diff --git a/code/modules/overmap/exoplanets/decor/_flora.dm b/code/modules/overmap/exoplanets/decor/_flora.dm
new file mode 100644
index 00000000000..202a605d3b6
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/_flora.dm
@@ -0,0 +1,22 @@
+/obj/structure/flora
+ name = "flora parent object"
+ desc = DESC_PARENT
+ anchored = TRUE
+ density = TRUE
+ var/cutting
+
+/obj/structure/flora/proc/dig_up(mob/user)
+ user.visible_message(SPAN_NOTICE("\The [user] begins digging up \the [src]..."))
+ if(do_after(user, 150))
+ if(Adjacent(user))
+ user.visible_message(SPAN_NOTICE("\The [user] removes \the [src]!"))
+ qdel(src)
+
+/obj/structure/flora/proc/can_dig()
+ return FALSE
+
+/obj/structure/flora/attackby(obj/item/I, mob/user)
+ if(I.is_shovel() && can_dig())
+ dig_up(user)
+ return
+ ..()
diff --git a/code/modules/overmap/exoplanets/turfs.dm b/code/modules/overmap/exoplanets/decor/_turfs.dm
similarity index 52%
rename from code/modules/overmap/exoplanets/turfs.dm
rename to code/modules/overmap/exoplanets/decor/_turfs.dm
index fb7e42c8662..8b9d5fc18a0 100644
--- a/code/modules/overmap/exoplanets/turfs.dm
+++ b/code/modules/overmap/exoplanets/decor/_turfs.dm
@@ -37,7 +37,7 @@
var/obj/item/stack/tile/T = C
if(T.use(1))
playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
- ChangeTurf(/turf/simulated/floor, FALSE, FALSE, TRUE)
+ ChangeTurf(/turf/simulated/floor, FALSE, FALSE, FALSE, TRUE)
/turf/simulated/floor/exoplanet/ex_act(severity)
switch(severity)
@@ -73,129 +73,8 @@
else if(update_neighbors)
turf_to_check.update_icon()
-//Water
-/turf/simulated/floor/exoplanet/water/update_icon()
- return
-
-/turf/simulated/floor/exoplanet/water/shallow
- name = "shallow water"
- icon = 'icons/misc/beach.dmi'
- icon_state = "seashallow"
- footstep_sound = /singleton/sound_category/water_footstep
- var/reagent_type = /singleton/reagent/water
-
-/turf/simulated/floor/exoplanet/water/shallow/attackby(obj/item/O, var/mob/living/user)
- var/obj/item/reagent_containers/RG = O
- if (reagent_type && istype(RG) && RG.is_open_container() && RG.reagents)
- RG.reagents.add_reagent(reagent_type, min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this))
- user.visible_message("[user] fills \the [RG] from \the [src].","You fill \the [RG] from \the [src].")
- else
- return ..()
-
-/turf/simulated/floor/exoplanet/water/update_dirt()
- return // Water doesn't become dirty
-
-//Ice
-/turf/simulated/floor/exoplanet/ice
- name = "ice"
- icon = 'icons/turf/snow.dmi'
- icon_state = "ice"
-
-/turf/simulated/floor/exoplanet/ice/update_icon()
- return
-
-/turf/simulated/floor/exoplanet/ice/dark
- icon_state = "icedark"
-
-//Snow
-/turf/simulated/floor/exoplanet/snow
- name = "snow"
- icon = 'icons/turf/smooth/snow40.dmi'
- icon_state = "snow"
- dirt_color = "#e3e7e8"
- layer = LOWER_ON_TURF_LAYER
- footstep_sound = /singleton/sound_category/snow_footstep
- smooth = SMOOTH_MORE | SMOOTH_BORDER | SMOOTH_NO_CLEAR_ICON
- smoothing_hints = SMOOTHHINT_CUT_F | SMOOTHHINT_ONLY_MATCH_TURF | SMOOTHHINT_TARGETS_NOT_UNIQUE
- canSmoothWith = list(
- /turf/simulated/floor/exoplanet/snow,
- /turf/simulated/wall,
- /turf/unsimulated/wall
- ) //Smooths with walls but not the inverse. This way to avoid layering over walls.
-
-/turf/simulated/floor/exoplanet/snow/Initialize()
- . = ..()
- pixel_x = -4
- pixel_y = -4
- icon_state = pick("snow[rand(1,2)]","snow0","snow0")
- queue_smooth_neighbors(src)
- queue_smooth(src)
-
-/turf/simulated/floor/exoplanet/snow/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- melt()
-
-/turf/simulated/floor/exoplanet/snow/melt()
- ChangeTurf(/turf/simulated/floor/exoplanet/permafrost)
-
-/turf/simulated/floor/exoplanet/permafrost
- name = "permafrost"
- icon = 'icons/turf/snow.dmi'
- icon_state = "permafrost"
- footstep_sound = /singleton/sound_category/asteroid_footstep
-
-//Grass
-/turf/simulated/floor/exoplanet/grass
- name = "grass"
- icon = 'icons/turf/jungle.dmi'
- icon_state = "greygrass"
- color = "#799c4b"
- footstep_sound = /singleton/sound_category/grass_footstep
-
-/turf/simulated/floor/exoplanet/grass/Initialize()
- . = ..()
- if(current_map.use_overmap)
- var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
- if(istype(E) && E.grass_color)
- color = E.grass_color
- if(!resources)
- resources = list()
- if(prob(5))
- resources[MATERIAL_URANIUM] = rand(1,3)
- if(prob(2))
- resources[MATERIAL_DIAMOND] = 1
-
-/turf/simulated/floor/exoplanet/grass/grove
- icon_state = "grove_grass1"
- color = null
- has_edge_icon = FALSE
-
-/turf/simulated/floor/exoplanet/grass/grove/Initialize()
- . = ..()
- icon_state = "grove_grass[rand(1,2)]"
-
-//Sand
-/turf/simulated/floor/exoplanet/desert
- name = "sand"
- desc = "It's coarse and gets everywhere."
- dirt_color = "#ae9e66"
- footstep_sound = /singleton/sound_category/sand_footstep
-
-/turf/simulated/floor/exoplanet/desert/Initialize()
- . = ..()
- icon_state = "desert[rand(0,4)]"
-
-/turf/simulated/floor/exoplanet/mineral
- name = "sand"
- desc = "It's coarse and gets everywhere."
- dirt_color = "#544c31"
- footstep_sound = /singleton/sound_category/sand_footstep
-
-//Concrete
-/turf/simulated/floor/exoplanet/concrete
- name = "concrete"
- desc = "Stone-like artificial material."
- icon = 'icons/turf/flooring/misc.dmi'
- icon_state = "concrete"
+/turf/simulated/floor/exoplanet/update_dirt()
+ return // it's already dirt, silly
//Special world edge turf,
/turf/unsimulated/planet_edge
diff --git a/code/modules/overmap/exoplanets/decor/flora/_bush.dm b/code/modules/overmap/exoplanets/decor/flora/_bush.dm
new file mode 100644
index 00000000000..e25e7c63749
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/flora/_bush.dm
@@ -0,0 +1,30 @@
+
+/obj/structure/flora/ausbushes
+ name = "bush"
+ desc = "A bush."
+ icon = 'icons/obj/flora/ausflora.dmi'
+ icon_state = "firstbush_1"
+ density = FALSE
+
+/obj/structure/flora/ausbushes/New()
+ ..()
+ icon_state = "firstbush_[rand(1, 4)]"
+
+/obj/structure/flora/ausbushes/attackby(var/obj/item/W, var/mob/user)
+ if(istype(W, /obj/item/material/scythe))
+ if(prob(50))
+ new /obj/item/stack/material/wood(get_turf(src), 2)
+ if(prob(40))
+ new /obj/item/stack/material/wood(get_turf(src), 4)
+ if(prob(10))
+ var/pickberry = pick(list(/obj/item/seeds/berryseed, /obj/item/seeds/blueberryseed))
+ new /obj/item/stack/material/wood(get_turf(src), 4)
+ new pickberry(get_turf(src), 4)
+ to_chat(user, SPAN_NOTICE("You find some seeds as you hack the bush away."))
+ to_chat(user, SPAN_NOTICE("You slice at the bush!"))
+ qdel(src)
+ playsound(src, 'sound/effects/woodcutting.ogg', 50, TRUE)
+ if(istype(W, /obj/item/material/hatchet)) // No items.
+ to_chat(user, SPAN_NOTICE("You chop at the bush!"))
+ qdel(src)
+ playsound(src, 'sound/effects/woodcutting.ogg', 50, TRUE)
diff --git a/code/modules/overmap/exoplanets/decor/flora/_rock.dm b/code/modules/overmap/exoplanets/decor/flora/_rock.dm
new file mode 100644
index 00000000000..c028720596e
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/flora/_rock.dm
@@ -0,0 +1,47 @@
+/obj/structure/flora/rock
+ name = "rock"
+ desc = "A rock."
+ icon = 'icons/obj/flora/rocks_grey.dmi'
+ icon_state = "basalt"
+
+/obj/structure/flora/rock/random/Initialize(mapload)
+ . = ..()
+ icon_state = "basalt[rand(1,3)]"
+
+/obj/structure/flora/rock/pile
+ name = "rocks"
+ desc = "A pile of rocks."
+ icon_state = "lavarocks"
+
+/obj/structure/flora/rock/pile/random/Initialize(mapload)
+ . = ..()
+ icon_state = "lavarocks[rand(1,3)]"
+
+/obj/structure/flora/rock/ice
+ name = "ice"
+ desc = "A large formation made of ice."
+ icon = 'icons/obj/flora/ice_rocks.dmi'
+ icon_state = "rock_1"
+
+/obj/structure/flora/rock/ice/Initialize(mapload)
+ . = ..()
+ icon_state = "rock_[rand(1,3)]"
+
+/obj/structure/flora/rock/snow
+ name = "snowy boulder"
+ desc = "A weathered boulder, coated in a fine dusting of snow."
+ icon = 'icons/obj/flora/snowrocks.dmi'
+ icon_state = "rocklarge1"
+
+/obj/structure/flora/rock/snow/Initialize(mapload)
+ . = ..()
+ icon_state = "rocklarge[rand(1,2)]"
+
+/obj/effect/floor_decal/snowrocks
+ name = "snow rocks"
+ icon = 'icons/obj/flora/snowrocks.dmi'
+ icon_state = "rocksmall1"
+
+/obj/effect/floor_decal/snowrocks/Initialize(mapload, newdir, newcolour, bypass, set_icon_state)
+ icon_state = "rocksmall[rand(1,2)]"
+ . = ..()
diff --git a/code/modules/overmap/exoplanets/decor/flora/_tree.dm b/code/modules/overmap/exoplanets/decor/flora/_tree.dm
new file mode 100644
index 00000000000..6bd7c6f1af9
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/flora/_tree.dm
@@ -0,0 +1,158 @@
+/obj/structure/flora/tree
+ name = "tree"
+ desc = "A tree."
+ density = TRUE
+ layer = 9
+ pixel_x = -16
+ var/max_chop_health = 180
+ var/chop_health = 180 //15 hits with steel hatchet, 5 with wielded fireaxe
+ var/fall_force = 60
+ var/list/contained_objects = list() //If it has anything except wood. Fruit, pinecones, animals, etc.
+ var/stumptype = /obj/structure/flora/stump //stump to make when chopped
+ var/static/list/fall_forbid = list(/obj/structure/flora, /obj/effect, /obj/structure/bonfire, /obj/structure/pit)
+
+/obj/structure/flora/tree/proc/update_desc()
+ desc = initial(desc)
+ switch(chop_health / max_chop_health)
+ if(0 to 0.25)
+ desc = " It looks like it's about to fall!"
+ if(0.26 to 0.5)
+ desc += " Just a bit more work and it'll fall!"
+ if(0.51 to 0.75)
+ desc += " It's been chopped at a few times."
+ if(0.76 to 0.95)
+ desc += " Looks like someone just started cutting it down."
+
+/obj/structure/flora/tree/attackby(obj/item/I, mob/user)
+ if(I.can_woodcut())
+ if(cutting)
+ return
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ cutting = TRUE
+ if(istype(I, /obj/item/material/twohanded/chainsaw))
+ var/obj/item/material/twohanded/chainsaw/C = I
+ if(C.powered)
+ user.visible_message(SPAN_NOTICE("\The [user] begins cutting down \the [src]..."), SPAN_NOTICE("You start cutting down \the [src]..."))
+ playsound(get_turf(user), 'sound/weapons/saw/chainsawhit.ogg', 60, 1)
+ shake_animation()
+ if(do_after(user, 50))
+ timber(user)
+ else
+ to_chat(user, SPAN_WARNING("Try turning \the [C] on first!"))
+ cutting = FALSE
+ return
+ else if(do_after(user, I.w_class * 5)) //Small windup
+ user.do_attack_animation(src)
+ shake_animation()
+ playsound(get_turf(src), 'sound/effects/woodcutting.ogg', 50, 1)
+ chop_health -= I.force
+ update_desc()
+ if(prob(20))
+ user.visible_message(SPAN_NOTICE("\The [user] chops at \the [src]."), SPAN_NOTICE("You chop at \the [src]."), SPAN_NOTICE("You hear someone chopping wood."))
+ if(prob(I.force/3))
+ var/list/valid_turfs = list()
+ for(var/turf/T in circle_range(src, 1))
+ if(T.contains_dense_objects())
+ continue
+ valid_turfs += T
+ if(!valid_turfs.len)
+ valid_turfs += get_turf(src)
+ var/obj/item/stack/material/wood/branch/B = new(pick(valid_turfs))
+ B.amount = 1
+ visible_message(SPAN_NOTICE("\The [B] falls from \the [src]."))
+
+ if(chop_health <= 0)
+ timber(user)
+ cutting = FALSE
+ return
+ ..()
+
+/obj/structure/flora/tree/proc/timber(mob/user)
+ var/turf/fall_loc //Where we will fall
+
+ //We prefer to fall directly away from the user if possible
+ var/turf/pref_loc = get_cardinal_step_away(src, user)
+ if(!pref_loc.contains_dense_objects(TRUE))
+ fall_loc = pref_loc
+
+ //Otherwise, we fall elsewhere
+ else
+ var/list/fall_spots = list()
+ for(var/turf/T in orange(1, src))
+ if(locate(user) in T.contents) //Won't fall on woodcutter
+ continue
+ if(T.contains_dense_objects(TRUE)) //Let's avoid dense objects but not mobs
+ continue
+ fall_spots += T
+
+ if(!fall_spots.len)
+ fall_loc = get_turf(src)
+ else
+ fall_loc = pick(fall_spots)
+ playsound(get_turf(src), 'sound/species/diona/gestalt_grow.ogg', 50)
+ for(var/atom/A in fall_loc.contents)
+ if(is_type_in_list(A, fall_forbid))
+ continue
+ if(isliving(A))
+ var/mob/living/L = A
+ visible_message(SPAN_WARNING("\The [src] crushes \the [L] under its weight!"))
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ var/obj/item/organ/external/affected = pick(H.organs)
+ affected.take_damage(fall_force)
+ else
+ if(L.mob_size <= fall_force / 5)
+ L.gib()
+ else
+ L.health -= fall_force
+ if(L.health <= 0)
+ L.gib()
+
+ if(isobj(A) && !istype(A, /obj/item/stack) && A != src)
+ var/obj/O = A
+ if(prob(fall_force * 0.75))
+ visible_message(SPAN_WARNING("\The [src] crushes \the [O] under its weight!"))
+ qdel(A)
+ new /obj/structure/flora/stump/log(fall_loc)
+ var/obj/item/stack/material/wood/branch/B = new(fall_loc)
+ B.amount = rand(5, 8)
+ new stumptype(get_turf(src))
+ qdel(src)
+
+/obj/structure/flora/stump
+ name = "stump"
+ desc = "Nature's chair."
+ icon = 'icons/obj/wood.dmi'
+ icon_state = "tree_stump"
+ density = FALSE
+ anchored = TRUE
+
+/obj/structure/flora/stump/can_dig()
+ return TRUE
+
+/obj/structure/flora/stump/log
+ name = "big log"
+ desc = "A sideways tree, but dead. Chop this into useable logs!"
+ anchored = FALSE
+ icon_state = "timber"
+
+/obj/structure/flora/stump/log/attackby(obj/item/I, mob/user)
+ if(I.can_woodcut())
+ if(cutting)
+ return
+ cutting = TRUE
+ var/chopsound = istype(I, /obj/item/material/twohanded/chainsaw) ? 'sound/weapons/saw/chainsawhit.ogg' : 'sound/effects/woodcutting.ogg'
+ playsound(get_turf(user), chopsound, 50, 1)
+ user.visible_message(SPAN_NOTICE("\The [user] begins chopping \the [src] into log sections."), SPAN_NOTICE("You begin chopping \the [src] into log sections."))
+ var/chopspeed = 1
+ if(istype(I, /obj/item/material/twohanded))
+ var/obj/item/material/twohanded/W = I
+ chopspeed = W.wielded ? 2 : 1
+ if(do_after(user, 100 / chopspeed))
+ user.visible_message(SPAN_NOTICE("\The [user] chops \the [src] into log sections."), SPAN_NOTICE("You chop \the [src] into log sections."))
+ var/obj/item/stack/material/wood/log/L = new(get_turf(src))
+ L.amount = rand(5, 8)
+ qdel(src)
+ cutting = FALSE
+ else
+ ..()
diff --git a/code/game/objects/structures/flora/adhomai.dm b/code/modules/overmap/exoplanets/decor/flora/adhomai.dm
similarity index 96%
rename from code/game/objects/structures/flora/adhomai.dm
rename to code/modules/overmap/exoplanets/decor/flora/adhomai.dm
index e35b6feaed4..20cdc265e6b 100644
--- a/code/game/objects/structures/flora/adhomai.dm
+++ b/code/modules/overmap/exoplanets/decor/flora/adhomai.dm
@@ -44,4 +44,4 @@
/obj/structure/flora/rock/adhomai/Initialize(mapload)
. = ..()
- icon_state = "rock[rand(1, 5)]"
\ No newline at end of file
+ icon_state = "rock[rand(1, 5)]"
diff --git a/code/modules/overmap/exoplanets/decor/flora/crystal.dm b/code/modules/overmap/exoplanets/decor/flora/crystal.dm
new file mode 100644
index 00000000000..80102da6e85
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/flora/crystal.dm
@@ -0,0 +1,34 @@
+/obj/structure/flora/tree/crystal
+ name = "crystalline tree"
+ desc = "An exotic growth that appears to be a tree-like form, though grown entirely out of crystal."
+ pixel_x = -32
+ icon = 'icons/obj/flora/crystal_trees.dmi'
+ icon_state = "gem"
+
+/obj/structure/flora/tree/crystal/Initialize(mapload)
+ . = ..()
+ icon_state = "gem[rand(1,2)]"
+
+/obj/structure/flora/tree/crystal/attackby(obj/item/I, mob/user)
+ return TRUE // could probably make this mineable but I'm lazy
+
+/obj/structure/flora/rock/spire
+ name = "crystal spire"
+ desc = "A crystalline structure suspended in mid-air."
+ icon = 'icons/obj/flora/crystal_trees.dmi'
+ icon_state = "spire"
+ pixel_x = -32
+ layer = ABOVE_ALL_MOB_LAYER // this is basically a tree
+
+/obj/structure/flora/rock/spire/Initialize(mapload)
+ . = ..()
+ icon_state = "spire[rand(1,3)]"
+
+/obj/effect/floor_decal/crystal
+ name = "crystals"
+ icon = 'icons/turf/crystal.dmi'
+ icon_state = "crystal_gen"
+
+/obj/effect/floor_decal/crystal/random/Initialize(mapload, newdir, newcolour, bypass, set_icon_state)
+ icon_state = "crystal_gen[rand(1,3)]"
+ . = ..()
diff --git a/code/modules/overmap/exoplanets/decor/flora/desert.dm b/code/modules/overmap/exoplanets/decor/flora/desert.dm
new file mode 100644
index 00000000000..9b08a72d219
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/flora/desert.dm
@@ -0,0 +1,53 @@
+/obj/structure/flora/tree/desert
+ name = "cactus tree"
+ icon = 'icons/obj/flora/desert_cactus_trees.dmi'
+ icon_state = "desert_tree"
+ desc = "A prickly cactus with a woody trunk."
+
+/obj/structure/flora/tree/desert/Initialize(mapload)
+ . = ..()
+ icon_state = "desert_tree[rand(1,2)]"
+
+/obj/structure/flora/tree/desert/small/Initialize(mapload)
+ . = ..()
+ icon_state = "desert_tree[rand(3,4)]"
+
+/obj/structure/flora/tree/desert/tiny/Initialize(mapload)
+ . = ..()
+ icon_state = "desert_tree[rand(5,6)]"
+
+/obj/structure/flora/grass/desert
+ name = "desert grass"
+ desc = "Alien scrubland."
+ icon = 'icons/obj/flora/desertflora.dmi'
+ icon_state = "desert_grass"
+
+/obj/structure/flora/grass/desert/Initialize()
+ . = ..()
+ icon_state = "desert_grass[rand(1,3)]"
+
+/obj/structure/flora/grass/desert/bush/Initialize()
+ . = ..()
+ icon_state = "desert_grass_bush[rand(1,4)]"
+
+/obj/structure/flora/rock/desert
+ desc = "A sand-swept rock."
+ icon = 'icons/obj/flora/desertflora.dmi'
+ icon_state = "desert_rock"
+
+/obj/structure/flora/rock/desert/Initialize()
+ . = ..()
+ icon_state = "desert_rock[rand(1,4)]"
+
+/obj/structure/flora/rock/desert/scrub/Initialize()
+ . = ..()
+ icon_state = "desert_rock[rand(5,8)]"
+
+/obj/effect/floor_decal/dune
+ name = "sand dune"
+ icon = 'icons/turf/decals/sand64x32.dmi'
+ icon_state = "drift"
+
+/obj/effect/floor_decal/dune/random/Initialize(mapload, newdir, newcolour, bypass, set_icon_state)
+ supplied_dir = pick(cardinal)
+ . = ..()
diff --git a/code/modules/overmap/exoplanets/decor/flora/generic_flora.dm b/code/modules/overmap/exoplanets/decor/flora/generic_flora.dm
new file mode 100644
index 00000000000..dcc62a81c4c
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/flora/generic_flora.dm
@@ -0,0 +1,130 @@
+/obj/structure/flora/tree/pine
+ name = "pine tree"
+ icon = 'icons/obj/flora/pinetrees.dmi'
+ icon_state = "pine_1"
+
+/obj/structure/flora/tree/pine/New()
+ ..()
+ icon_state = "pine_[rand(1, 3)]"
+
+/obj/structure/flora/tree/pine/xmas
+ name = "xmas tree"
+ icon = 'icons/obj/flora/pinetrees.dmi'
+ icon_state = "pine_c"
+
+/obj/structure/flora/tree/pine/xmas/New()
+ ..()
+ icon_state = "pine_c"
+
+/obj/structure/flora/tree/dead
+ icon = 'icons/obj/flora/deadtrees.dmi'
+ icon_state = "tree_1"
+
+/obj/structure/flora/tree/dead/New()
+ ..()
+ icon_state = "tree_[rand(1, 6)]"
+
+/obj/structure/flora/ausbushes/reedbush
+ icon_state = "reedbush_1"
+
+/obj/structure/flora/ausbushes/reedbush/New()
+ ..()
+ icon_state = "reedbush_[rand(1, 4)]"
+
+/obj/structure/flora/ausbushes/leafybush
+ icon_state = "leafybush_1"
+
+/obj/structure/flora/ausbushes/leafybush/New()
+ ..()
+ icon_state = "leafybush_[rand(1, 3)]"
+
+/obj/structure/flora/ausbushes/palebush
+ icon_state = "palebush_1"
+
+/obj/structure/flora/ausbushes/palebush/New()
+ ..()
+ icon_state = "palebush_[rand(1, 4)]"
+
+/obj/structure/flora/ausbushes/stalkybush
+ icon_state = "stalkybush_1"
+
+/obj/structure/flora/ausbushes/stalkybush/New()
+ ..()
+ icon_state = "stalkybush_[rand(1, 3)]"
+
+/obj/structure/flora/ausbushes/grassybush
+ icon_state = "grassybush_1"
+
+/obj/structure/flora/ausbushes/grassybush/New()
+ ..()
+ icon_state = "grassybush_[rand(1, 4)]"
+
+/obj/structure/flora/ausbushes/fernybush
+ icon_state = "fernybush_1"
+
+/obj/structure/flora/ausbushes/fernybush/New()
+ ..()
+ icon_state = "fernybush_[rand(1, 3)]"
+
+/obj/structure/flora/ausbushes/sunnybush
+ icon_state = "sunnybush_1"
+
+/obj/structure/flora/ausbushes/sunnybush/New()
+ ..()
+ icon_state = "sunnybush_[rand(1, 3)]"
+
+/obj/structure/flora/ausbushes/genericbush
+ icon_state = "genericbush_1"
+
+/obj/structure/flora/ausbushes/genericbush/New()
+ ..()
+ icon_state = "genericbush_[rand(1, 4)]"
+
+/obj/structure/flora/ausbushes/pointybush
+ icon_state = "pointybush_1"
+
+/obj/structure/flora/ausbushes/pointybush/New()
+ ..()
+ icon_state = "pointybush_[rand(1, 4)]"
+
+/obj/structure/flora/ausbushes/lavendergrass
+ icon_state = "lavendergrass_1"
+
+/obj/structure/flora/ausbushes/lavendergrass/New()
+ ..()
+ icon_state = "lavendergrass_[rand(1, 4)]"
+
+/obj/structure/flora/ausbushes/ywflowers
+ icon_state = "ywflowers_1"
+
+/obj/structure/flora/ausbushes/ywflowers/New()
+ ..()
+ icon_state = "ywflowers_[rand(1, 4)]"
+
+/obj/structure/flora/ausbushes/brflowers
+ icon_state = "brflowers_1"
+
+/obj/structure/flora/ausbushes/brflowers/New()
+ ..()
+ icon_state = "brflowers_[rand(1, 3)]"
+
+/obj/structure/flora/ausbushes/ppflowers
+ icon_state = "ppflowers_1"
+
+/obj/structure/flora/ausbushes/ppflowers/New()
+ ..()
+ icon_state = "ppflowers_[rand(1, 3)]"
+
+/obj/structure/flora/ausbushes/sparsegrass
+ icon_state = "sparsegrass_1"
+
+/obj/structure/flora/ausbushes/sparsegrass/New()
+ ..()
+ icon_state = "sparsegrass_[rand(1, 3)]"
+
+/obj/structure/flora/ausbushes/fullgrass
+ icon_state = "fullgrass_1"
+
+/obj/structure/flora/ausbushes/fullgrass/New()
+ ..()
+ icon_state = "fullgrass_[rand(1, 3)]"
diff --git a/code/game/objects/structures/flora/grove.dm b/code/modules/overmap/exoplanets/decor/flora/grove.dm
similarity index 100%
rename from code/game/objects/structures/flora/grove.dm
rename to code/modules/overmap/exoplanets/decor/flora/grove.dm
diff --git a/code/modules/overmap/exoplanets/decor/flora/jungle.dm b/code/modules/overmap/exoplanets/decor/flora/jungle.dm
new file mode 100644
index 00000000000..127ef738947
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/flora/jungle.dm
@@ -0,0 +1,110 @@
+/obj/effect/floor_decal/junglegrass
+ name = "jungle grass"
+ icon = 'icons/obj/flora/jungleflora.dmi'
+ icon_state = "grassb"
+
+/obj/effect/floor_decal/junglegrass/random/Initialize(mapload, newdir, newcolour, bypass, set_icon_state)
+ icon_state = "grassb[rand(1,5)]"
+ . = ..()
+
+/obj/effect/floor_decal/junglegrass/dense
+ icon_state = "grassa"
+
+/obj/effect/floor_decal/junglegrass/dense/random/Initialize(mapload, newdir, newcolour, bypass, set_icon_state)
+ icon_state = "grassa[rand(1,5)]"
+ . = ..()
+
+/obj/effect/floor_decal/junglegrass/rocky
+ icon_state = "rock"
+
+/obj/effect/floor_decal/junglegrass/rocky/random/Initialize(mapload, newdir, newcolour, bypass, set_icon_state)
+ icon_state = "rock[rand(1,5)]"
+ . = ..()
+
+/obj/structure/flora/bush/jungle
+ name = "jungle fern"
+ desc = "A leafy, squat plant, accustomed to the forest floor."
+ icon = 'icons/obj/flora/jungleflora.dmi'
+ icon_state = "busha"
+
+/obj/structure/flora/bush/jungle/large
+ name = "large jungle fern"
+ desc = "A lush and oversized plant, clearly thriving in the jungle."
+ icon = 'icons/obj/flora/largejungleflora.dmi'
+ icon_state = "bush"
+ pixel_x = -16
+ pixel_y = -16
+ layer = ABOVE_ALL_MOB_LAYER
+
+/obj/structure/flora/bush/jungle/large/random/Initialize()
+ . = ..()
+ icon_state = "bush[rand(1,3)]"
+
+/obj/structure/flora/bush/jungle/b
+ icon_state = "bushb"
+
+/obj/structure/flora/bush/jungle/c
+ icon_state = "bushc"
+
+/obj/structure/flora/bush/jungle/random/Initialize()
+ . = ..()
+ icon_state = "busha[rand(1,3)]"
+
+/obj/structure/flora/bush/jungle/b/random/Initialize()
+ . = ..()
+ icon_state = "bushb[rand(1,3)]"
+
+/obj/structure/flora/bush/jungle/c/random/Initialize()
+ . = ..()
+ icon_state = "bushc[rand(1,3)]"
+
+//Jungle grass
+/obj/structure/flora/grass/jungle
+ name = "jungle grass"
+ desc = "Thick alien flora."
+ icon = 'icons/obj/flora/jungleflora.dmi'
+ icon_state = "grassa"
+
+/obj/structure/flora/grass/jungle/b
+ icon_state = "grassb"
+
+/obj/structure/flora/tree/jungle
+ name = "tree"
+ icon_state = "tree"
+ desc = "A lush and healthy tree."
+ icon = 'icons/obj/flora/jungletrees.dmi'
+ pixel_x = -48
+ pixel_y = -20
+
+/obj/structure/flora/tree/jungle/random/Initialize(mapload)
+ . = ..()
+ icon_state = "tree[rand(1,6)]"
+
+/obj/structure/flora/tree/jungle/small
+ pixel_y = 0
+ pixel_x = -32
+ icon = 'icons/obj/flora/jungletreesmall.dmi'
+
+/obj/structure/flora/tree/jungle/small/random/Initialize(mapload)
+ . = ..()
+ icon_state = "tree[rand(1,6)]"
+
+/obj/structure/flora/tree/jungle/small/patience
+ name = "Patience"
+ desc = "A lush and healthy tree. A small golden plaque at its base reads its name, in plain text, Patience."
+ icon_state = "patiencebottom"
+ density = FALSE
+ layer = 3
+
+/obj/structure/flora/tree/jungle/small/patience_top
+ name = "Patience"
+ desc = "A lush and healthy tree. A small golden plaque at its base reads its name, in plain text, Patience."
+ icon_state = "patiencetop"
+ density = TRUE
+ pixel_y = -32
+
+/obj/structure/flora/tree/jungle/small/patience/Initialize()
+ . = ..()
+ var/turf/T = get_step(src, NORTH)
+ if(T)
+ new /obj/structure/flora/tree/jungle/small/patience_top(T)
diff --git a/code/modules/overmap/exoplanets/decor/flora/marsh.dm b/code/modules/overmap/exoplanets/decor/flora/marsh.dm
new file mode 100644
index 00000000000..083feae3a89
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/flora/marsh.dm
@@ -0,0 +1,31 @@
+/obj/structure/flora/tree/mushroom
+ name = "fungal tree"
+ desc = "Some sort of woody fungal growth, grown to extreme proportions."
+ icon = 'icons/obj/flora/fungaltrees.dmi'
+ icon_state = "shroom"
+
+/obj/structure/flora/tree/mushroom/Initialize(mapload)
+ . = ..()
+ icon_state = "shroom[rand(1,2)]"
+ if(prob(5))
+ icon_state = "shroom3"
+ desc += " This one appears to have split wide open."
+
+/obj/structure/flora/bush/mushroom
+ name = "mushroom"
+ desc = "A rather large variety of fungus."
+ icon = 'icons/obj/flora/fungalflora.dmi'
+ icon_state = "fungus_bush"
+
+/obj/structure/flora/bush/mushroom/Initialize()
+ . = ..()
+ icon_state = "fungus_bush[rand(1,3)]"
+
+/obj/effect/floor_decal/fungus
+ name = "fungal growth"
+ icon = 'icons/obj/flora/fungalflora.dmi'
+ icon_state = "fungus"
+
+/obj/effect/floor_decal/fungus/random/Initialize(mapload, newdir, newcolour, bypass, set_icon_state)
+ icon_state = "fungus[rand(1,9)]"
+ . = ..()
diff --git a/code/game/objects/structures/flora/potted.dm b/code/modules/overmap/exoplanets/decor/flora/potted.dm
similarity index 100%
rename from code/game/objects/structures/flora/potted.dm
rename to code/modules/overmap/exoplanets/decor/flora/potted.dm
diff --git a/code/game/objects/structures/flora/snow.dm b/code/modules/overmap/exoplanets/decor/flora/snow.dm
similarity index 100%
rename from code/game/objects/structures/flora/snow.dm
rename to code/modules/overmap/exoplanets/decor/flora/snow.dm
diff --git a/code/game/objects/structures/monolith.dm b/code/modules/overmap/exoplanets/decor/objs/monolith.dm
similarity index 100%
rename from code/game/objects/structures/monolith.dm
rename to code/modules/overmap/exoplanets/decor/objs/monolith.dm
diff --git a/code/game/objects/structures/pit.dm b/code/modules/overmap/exoplanets/decor/objs/pit.dm
similarity index 100%
rename from code/game/objects/structures/pit.dm
rename to code/modules/overmap/exoplanets/decor/objs/pit.dm
diff --git a/code/modules/overmap/exoplanets/decor/turfs/barren.dm b/code/modules/overmap/exoplanets/decor/turfs/barren.dm
new file mode 100644
index 00000000000..a519211ccc8
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/turfs/barren.dm
@@ -0,0 +1,19 @@
+/turf/simulated/floor/exoplanet/barren
+ name = "ground"
+ icon = 'icons/turf/flooring/asteroid.dmi'
+ icon_state = "asteroid"
+
+/turf/simulated/floor/exoplanet/barren/update_icon()
+ overlays.Cut()
+ if(prob(20))
+ overlays += image('icons/turf/decals/decals.dmi', "asteroid[rand(0,9)]")
+
+/turf/simulated/floor/exoplanet/barren/Initialize()
+ . = ..()
+ update_icon()
+
+/turf/simulated/floor/exoplanet/barren/raskara
+ color = "#373737"
+
+/turf/simulated/floor/exoplanet/barren/raskara/update_icon()
+ overlays.Cut()
diff --git a/code/modules/overmap/exoplanets/decor/turfs/concrete.dm b/code/modules/overmap/exoplanets/decor/turfs/concrete.dm
new file mode 100644
index 00000000000..d0692b3aa6f
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/turfs/concrete.dm
@@ -0,0 +1,5 @@
+/turf/simulated/floor/exoplanet/concrete
+ name = "concrete"
+ desc = "Stone-like artificial material."
+ icon = 'icons/turf/flooring/misc.dmi'
+ icon_state = "concrete"
diff --git a/code/modules/overmap/exoplanets/decor/turfs/crystal.dm b/code/modules/overmap/exoplanets/decor/turfs/crystal.dm
new file mode 100644
index 00000000000..3223782b214
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/turfs/crystal.dm
@@ -0,0 +1,6 @@
+/turf/simulated/floor/exoplanet/crystal
+ name = "quartz"
+ desc = "A tough, compacted mineral surface, polished to a mirror sheen."
+ icon = 'icons/turf/crystal.dmi'
+ icon_state = "crystal"
+ footstep_sound = /singleton/sound_category/glasscrack_sound
diff --git a/code/modules/overmap/exoplanets/decor/turfs/grass.dm b/code/modules/overmap/exoplanets/decor/turfs/grass.dm
new file mode 100644
index 00000000000..7937ed1ca63
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/turfs/grass.dm
@@ -0,0 +1,45 @@
+/turf/simulated/floor/exoplanet/grass
+ name = "grass"
+ icon = 'icons/turf/jungle.dmi'
+ icon_state = "greygrass"
+ color = "#799c4b"
+ footstep_sound = /singleton/sound_category/grass_footstep
+
+/turf/simulated/floor/exoplanet/grass/Initialize()
+ . = ..()
+ if(current_map.use_overmap)
+ var/obj/effect/overmap/visitable/sector/exoplanet/E = map_sectors["[z]"]
+ if(color && istype(E) && E.grass_color)
+ color = E.grass_color
+ if(!resources)
+ resources = list()
+ if(prob(5))
+ resources[MATERIAL_URANIUM] = rand(1,3)
+ if(prob(2))
+ resources[MATERIAL_DIAMOND] = 1
+
+/turf/simulated/floor/exoplanet/grass/grove
+ icon_state = "grove_grass1"
+ color = null
+ has_edge_icon = FALSE
+
+/turf/simulated/floor/exoplanet/grass/grove/Initialize()
+ . = ..()
+ icon_state = "grove_grass[rand(1,2)]"
+
+/turf/simulated/floor/exoplanet/grass/stalk
+ icon = 'icons/turf/total_floors.dmi'
+ icon_state = "grass_stalk"
+ color = null
+ has_edge_icon = null
+
+/turf/simulated/floor/exoplanet/grass/marsh
+ icon = 'icons/turf/fungal_marsh.dmi'
+ icon_state = "marsh"
+ color = null
+ has_edge_icon = null
+ footstep_sound = /singleton/sound_category/water_footstep
+
+/turf/simulated/floor/exoplanet/grass/marsh/Initialize()
+ . = ..()
+ icon_state = "marsh[rand(1,8)]"
diff --git a/code/modules/overmap/exoplanets/decor/turfs/ice.dm b/code/modules/overmap/exoplanets/decor/turfs/ice.dm
new file mode 100644
index 00000000000..60ecf40a367
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/turfs/ice.dm
@@ -0,0 +1,10 @@
+/turf/simulated/floor/exoplanet/ice
+ name = "ice"
+ icon = 'icons/turf/snow.dmi'
+ icon_state = "ice"
+
+/turf/simulated/floor/exoplanet/ice/update_icon()
+ return
+
+/turf/simulated/floor/exoplanet/ice/dark
+ icon_state = "icedark"
diff --git a/code/modules/overmap/exoplanets/decor/turfs/mineral.dm b/code/modules/overmap/exoplanets/decor/turfs/mineral.dm
new file mode 100644
index 00000000000..c359a47fa4c
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/turfs/mineral.dm
@@ -0,0 +1,16 @@
+/turf/simulated/floor/exoplanet/mineral
+ name = "sand"
+ desc = "It's coarse and gets everywhere."
+ dirt_color = "#544c31"
+ footstep_sound = /singleton/sound_category/sand_footstep
+
+/turf/simulated/floor/exoplanet/mineral/adhomai
+ name = "icy rock"
+ icon = 'icons/turf/flooring/ice_cavern.dmi'
+ icon_state = "icy_rock"
+ temperature = T0C - 5
+ has_edge_icon = FALSE
+
+/turf/simulated/floor/exoplanet/mineral/adhomai/Initialize(mapload)
+ . = ..()
+ icon_state = "icy_rock[rand(1,19)]"
diff --git a/code/modules/overmap/exoplanets/decor/turfs/sand.dm b/code/modules/overmap/exoplanets/decor/turfs/sand.dm
new file mode 100644
index 00000000000..aaeca768575
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/turfs/sand.dm
@@ -0,0 +1,15 @@
+/turf/simulated/floor/exoplanet/desert
+ name = "sand"
+ desc = "It's coarse and gets everywhere."
+ icon = 'icons/turf/desert.dmi'
+ icon_state = "desert"
+ dirt_color = "#ae9e66"
+ footstep_sound = /singleton/sound_category/sand_footstep
+
+/turf/simulated/floor/exoplanet/desert/Initialize()
+ . = ..()
+ icon_state = "desert[rand(1,4)]"
+
+/turf/simulated/floor/exoplanet/desert/rough/Initialize()
+ . = ..()
+ icon_state = "desert[rand(5,7)]"
diff --git a/code/modules/overmap/exoplanets/decor/turfs/snow.dm b/code/modules/overmap/exoplanets/decor/turfs/snow.dm
new file mode 100644
index 00000000000..3d0f9d51c80
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/turfs/snow.dm
@@ -0,0 +1,34 @@
+/turf/simulated/floor/exoplanet/snow
+ name = "snow"
+ icon = 'icons/turf/smooth/snow40.dmi'
+ icon_state = "snow"
+ dirt_color = "#e3e7e8"
+ layer = LOWER_ON_TURF_LAYER
+ footstep_sound = /singleton/sound_category/snow_footstep
+ smooth = SMOOTH_MORE | SMOOTH_BORDER | SMOOTH_NO_CLEAR_ICON
+ smoothing_hints = SMOOTHHINT_CUT_F | SMOOTHHINT_ONLY_MATCH_TURF | SMOOTHHINT_TARGETS_NOT_UNIQUE
+ canSmoothWith = list(
+ /turf/simulated/floor/exoplanet/snow,
+ /turf/simulated/wall,
+ /turf/unsimulated/wall
+ ) //Smooths with walls but not the inverse. This way to avoid layering over walls.
+
+/turf/simulated/floor/exoplanet/snow/Initialize()
+ . = ..()
+ pixel_x = -4
+ pixel_y = -4
+ icon_state = pick("snow[rand(1,2)]","snow0","snow0")
+ queue_smooth_neighbors(src)
+ queue_smooth(src)
+
+/turf/simulated/floor/exoplanet/snow/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ melt()
+
+/turf/simulated/floor/exoplanet/snow/melt()
+ ChangeTurf(/turf/simulated/floor/exoplanet/permafrost)
+
+/turf/simulated/floor/exoplanet/permafrost
+ name = "permafrost"
+ icon = 'icons/turf/snow.dmi'
+ icon_state = "permafrost"
+ footstep_sound = /singleton/sound_category/asteroid_footstep
diff --git a/code/modules/overmap/exoplanets/decor/turfs/water.dm b/code/modules/overmap/exoplanets/decor/turfs/water.dm
new file mode 100644
index 00000000000..eab2645015c
--- /dev/null
+++ b/code/modules/overmap/exoplanets/decor/turfs/water.dm
@@ -0,0 +1,20 @@
+/turf/simulated/floor/exoplanet/water/update_icon()
+ return
+
+/turf/simulated/floor/exoplanet/water/update_dirt()
+ return // Water doesn't become dirty
+
+/turf/simulated/floor/exoplanet/water/shallow
+ name = "shallow water"
+ icon = 'icons/misc/beach.dmi'
+ icon_state = "seashallow"
+ footstep_sound = /singleton/sound_category/water_footstep
+ var/reagent_type = /singleton/reagent/water
+
+/turf/simulated/floor/exoplanet/water/shallow/attackby(obj/item/O, var/mob/living/user)
+ var/obj/item/reagent_containers/RG = O
+ if (reagent_type && istype(RG) && RG.is_open_container() && RG.reagents)
+ RG.reagents.add_reagent(reagent_type, min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this))
+ user.visible_message("[user] fills \the [RG] from \the [src].","You fill \the [RG] from \the [src].")
+ else
+ return ..()
diff --git a/code/modules/overmap/exoplanets/exoplanet.dm b/code/modules/overmap/exoplanets/exoplanet.dm
index 8ba26894691..ba0cf68548c 100644
--- a/code/modules/overmap/exoplanets/exoplanet.dm
+++ b/code/modules/overmap/exoplanets/exoplanet.dm
@@ -44,8 +44,6 @@
var/list/possible_themes = list(/datum/exoplanet_theme)
var/datum/exoplanet_theme/theme
- var/list/map_generators = list()
-
var/features_budget = 4
var/list/possible_features = list()
var/list/spawned_features
@@ -210,14 +208,16 @@
repopulate_types |= M.type
/obj/effect/overmap/visitable/sector/exoplanet/proc/generate_map()
+ if(!istype(theme))
+ CRASH("Exoplanet [src] attempted to generate without valid theme!")
if(plant_colors)
var/list/grasscolors = plant_colors.Copy()
grasscolors -= "RANDOM"
if(length(grasscolors))
grass_color = pick(grasscolors)
- if(istype(theme))
- theme.before_map_generation(src)
+ theme.before_map_generation(src)
+ theme.generate_map(src, map_z[1], 1 + TRANSITIONEDGE, 1 + TRANSITIONEDGE, maxx - (1 + TRANSITIONEDGE), maxy - (1 + TRANSITIONEDGE))
for (var/zlevel in map_z)
var/list/edges
@@ -227,31 +227,12 @@
edges |= block(locate(1, maxy-TRANSITIONEDGE, zlevel),locate(maxx, maxy, zlevel))
for (var/turf/T in edges)
T.ChangeTurf(/turf/unsimulated/planet_edge)
- var/padding = TRANSITIONEDGE
- for (var/map_type in map_generators)
- if (ispath(map_type, /datum/random_map/noise/exoplanet))
- new map_type(null,padding,padding,zlevel,maxx-padding,maxy-padding,0,1,1,planetary_area, plant_colors, theme)
- else
- new map_type(null,1,1,zlevel,maxx,maxy,0,1,1,planetary_area)
+
+ theme.cleanup(src, map_z[1], 1 + TRANSITIONEDGE, 1 + TRANSITIONEDGE, maxx - (1 + TRANSITIONEDGE), maxy - (1 + TRANSITIONEDGE))
/obj/effect/overmap/visitable/sector/exoplanet/proc/generate_features()
spawned_features = seedRuins(map_z, features_budget, possible_features, /area/exoplanet, maxx, maxy)
-/obj/effect/overmap/visitable/sector/exoplanet/proc/get_biostuff(var/datum/random_map/noise/exoplanet/random_map)
- if(!istype(random_map))
- return
- seeds += random_map.small_flora_types
- if(random_map.big_flora_types)
- seeds += random_map.big_flora_types
- for(var/mob/living/simple_animal/A in living_mob_list)
- if(A.z in map_z)
- animals += A
- death_event.register(A, src, PROC_REF(remove_animal))
- destroyed_event.register(A, src, PROC_REF(remove_animal))
- max_animal_count = animals.len
- for(var/type in random_map.fauna_types)
- mobs_to_tolerate[type] = TRUE
-
/obj/effect/overmap/visitable/sector/exoplanet/proc/update_biome()
for(var/datum/seed/S as anything in seeds)
adapt_seed(S)
@@ -481,8 +462,3 @@
colors += gas_data.tile_overlay_color[g]
if(colors.len)
return MixColors(colors)
-
-/area/exoplanet
- name = "\improper Planetary surface"
- ambience = list('sound/effects/wind/wind_2_1.ogg','sound/effects/wind/wind_2_2.ogg','sound/effects/wind/wind_3_1.ogg','sound/effects/wind/wind_4_1.ogg','sound/effects/wind/wind_4_2.ogg','sound/effects/wind/wind_5_1.ogg')
- always_unpowered = 1
diff --git a/code/modules/overmap/exoplanets/random_map.dm b/code/modules/overmap/exoplanets/random_map.dm
deleted file mode 100644
index 6c097ef3909..00000000000
--- a/code/modules/overmap/exoplanets/random_map.dm
+++ /dev/null
@@ -1,132 +0,0 @@
-/datum/random_map/noise/exoplanet
- descriptor = "exoplanet"
- smoothing_iterations = 1
-
- var/water_level
- var/water_level_min = 0
- var/water_level_max = 5
- var/land_type = /turf/simulated/floor
- var/water_type
- var/datum/exoplanet_theme/planet_theme
-
- //intended x*y size, used to adjust spawn probs
- var/intended_x = 150
- var/intended_y = 150
- var/flora_prob = 10
- var/flora_diversity = 4
- var/fauna_prob = 2
- var/megafauna_spawn_prob = 0.5 //chance that a given fauna mob will instead be a megafauna
-
- var/list/fauna_types = list()
- var/list/small_flora_types = list()
- var/list/big_flora_types = list()
- var/list/plantcolors = list("RANDOM")
- var/list/grass_cache
-
-/datum/random_map/noise/exoplanet/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly, var/do_not_apply, var/do_not_announce, var/never_be_priority = 0, var/used_area, var/list/_plant_colors, var/datum/exoplanet_theme/_planet_theme)
- log_debug("Generating Random Exoplanet Map with tx: [tx], ty: [ty], tz: [tz], tlx: [tlx], tly: [tly]")
- target_turf_type = world.turf
- water_level = rand(water_level_min,water_level_max)
- //automagically adjust probs for bigger maps to help with lag
- var/size_mod = intended_x / tlx * intended_y / tly
- flora_prob *= size_mod
- fauna_prob *= size_mod
- if(_plant_colors)
- plantcolors = _plant_colors
- if(istype(_planet_theme))
- planet_theme = _planet_theme
- generate_flora()
- ..()
-
- current_map.base_turf_by_z[num2text(tz)] = land_type
-
-/datum/random_map/noise/exoplanet/proc/is_edge_turf(turf/T)
- return T.x <= TRANSITIONEDGE || T.x >= (limit_x - TRANSITIONEDGE + 1) || T.y <= TRANSITIONEDGE || T.y >= (limit_y - TRANSITIONEDGE + 1)
-
-/datum/random_map/noise/exoplanet/get_map_char(var/value)
- if(water_type && noise2value(value) < water_level)
- return "~"
- return "[noise2value(value)]"
-
-/datum/random_map/noise/exoplanet/get_appropriate_path(var/value)
- if(water_type && noise2value(value) < water_level)
- return water_type
- else
- return land_type
-
-/datum/random_map/noise/exoplanet/get_additional_spawns(var/value, var/turf/T)
- if(istype(planet_theme))
- planet_theme.on_turf_generation(T, use_area)
- if(is_edge_turf(T))
- return
- if(T.is_wall())
- return
- var/parsed_value = noise2value(value)
- switch(parsed_value)
- if(2 to 3)
- if(prob(fauna_prob))
- spawn_fauna(T)
- if(5 to 6)
- if(flora_prob > 5 && prob(flora_prob * 5))
- spawn_grass(T)
- if(prob(flora_prob/3))
- spawn_flora(T)
- if(7 to 9)
- if(flora_prob > 1 && prob(flora_prob * 10))
- spawn_grass(T)
- if(prob(flora_prob))
- spawn_flora(T)
-
-/datum/random_map/noise/exoplanet/proc/spawn_fauna(var/turf/T)
- if(LAZYLEN(fauna_types))
- var/beastie = pick(fauna_types)
- new beastie(T)
-
-/datum/random_map/noise/exoplanet/proc/generate_flora()
- for(var/i = 1 to flora_diversity)
- var/datum/seed/S = new()
- S.randomize()
- var/planticon = "alien[rand(1,4)]"
- S.set_trait(TRAIT_PRODUCT_ICON,planticon)
- S.set_trait(TRAIT_PLANT_ICON,planticon)
- var/color = pick(plantcolors)
- if(color == "RANDOM")
- color = get_random_colour(0,75,190)
- S.set_trait(TRAIT_PLANT_COLOUR,color)
- var/carnivore_prob = rand(100)
- if(carnivore_prob < 10)
- S.set_trait(TRAIT_CARNIVOROUS,2)
- S.set_trait(TRAIT_SPREAD,1)
- else if(carnivore_prob < 20)
- S.set_trait(TRAIT_CARNIVOROUS,1)
- small_flora_types += S
-
-/datum/random_map/noise/exoplanet/proc/get_grass_overlay()
- var/grass_num = "[rand(1,6)]"
- if(!LAZYACCESS(grass_cache, grass_num))
- var/color = pick(plantcolors)
- if(color == "RANDOM")
- color = get_random_colour(0,75,190)
- var/image/grass = overlay_image('icons/obj/flora/greygrass.dmi', "grass_[grass_num]", color, RESET_COLOR)
- grass.underlays += overlay_image('icons/obj/flora/greygrass.dmi', "grass_[grass_num]_shadow", null, RESET_COLOR)
- LAZYSET(grass_cache, grass_num, grass)
- return grass_cache[grass_num]
-
-/datum/random_map/noise/exoplanet/proc/spawn_flora(var/turf/T, var/big)
- if(big)
- if(LAZYLEN(big_flora_types))
- new /obj/machinery/portable_atmospherics/hydroponics/soil/invisible(T, pick(big_flora_types), 1)
- for(var/turf/neighbor as anything in RANGE_TURFS(1,T))
- spawn_grass(neighbor)
- else
- if(LAZYLEN(small_flora_types))
- new /obj/machinery/portable_atmospherics/hydroponics/soil/invisible(T, pick(small_flora_types), 1)
- spawn_grass(T)
-
-/datum/random_map/noise/exoplanet/proc/spawn_grass(var/turf/T)
- if(istype(T, water_type))
- return
- if(locate(/obj/effect/floor_decal) in T)
- return
- var/obj/effect/floor_decal/FD = new /obj/effect/floor_decal(T)
- FD.appearance = get_grass_overlay()
diff --git a/code/modules/overmap/exoplanets/theme.dm b/code/modules/overmap/exoplanets/theme.dm
deleted file mode 100644
index a6610e4218f..00000000000
--- a/code/modules/overmap/exoplanets/theme.dm
+++ /dev/null
@@ -1,82 +0,0 @@
-/datum/exoplanet_theme
- var/name = "Nothing Special"
- var/list/surface_turfs = list()
- var/surface_color
-
-/datum/exoplanet_theme/proc/before_map_generation(obj/effect/overmap/visitable/sector/exoplanet/E)
- if(E.rock_colors)
- surface_color = pick(E.rock_colors)
-
-/datum/exoplanet_theme/proc/on_turf_generation(turf/T, var/area/use_area)
- if(surface_color && is_type_in_list(T, surface_turfs))
- T.color = surface_color
-
-/datum/exoplanet_theme/proc/get_planet_image_extra()
-
-/datum/exoplanet_theme/mountains
- name = "Mountains"
- surface_turfs = list(
- /turf/simulated/mineral,
- /turf/unsimulated/floor/asteroid/ash
- )
- var/cave_path = /datum/random_map/automata/cave_system/mountains
-
-/datum/exoplanet_theme/mountains/get_planet_image_extra()
- var/image/res = image('icons/skybox/planet.dmi', "mountains")
- res.color = surface_color
- return res
-
-/datum/exoplanet_theme/mountains/before_map_generation(obj/effect/overmap/visitable/sector/exoplanet/E)
- ..()
- for(var/zlevel in E.map_z)
- new cave_path(null,TRANSITIONEDGE,TRANSITIONEDGE,zlevel,E.maxx-TRANSITIONEDGE,E.maxy-TRANSITIONEDGE,0,1,1, E.planetary_area, src)
-
-/datum/exoplanet_theme/mountains/on_turf_generation(turf/simulated/mineral/T, var/area/use_area)
- ..()
- if(use_area && istype(T))
- T.mined_turf = use_area.base_turf
-
-/datum/exoplanet_theme/mountains/phoron
- cave_path = /datum/random_map/automata/cave_system/mountains/phoron
-
-/datum/exoplanet_theme/mountains/breathable
- cave_path = /datum/random_map/automata/cave_system/mountains/breathable
-
-/datum/exoplanet_theme/mountains/adhomai
- cave_path = /datum/random_map/automata/cave_system/mountains/adhomai
-
-/datum/random_map/automata/cave_system/mountains
- iterations = 2
- descriptor = "space mountains"
- wall_type = /turf/simulated/mineral
- cell_threshold = 6
- var/rock_color
-
-/datum/random_map/automata/cave_system/mountains/phoron
- mineral_sparse = /turf/simulated/mineral/random/phoron
- mineral_rich = /turf/simulated/mineral/random/high_chance/phoron
-
-/datum/random_map/automata/cave_system/mountains/breathable
- wall_type = /turf/simulated/mineral/planet
- mineral_sparse = /turf/simulated/mineral/random/exoplanet
- mineral_rich = /turf/simulated/mineral/random/high_chance/exoplanet
- floor_type = /turf/simulated/floor/exoplanet/mineral
- use_area = FALSE
-
-/datum/random_map/automata/cave_system/mountains/adhomai
- wall_type = /turf/simulated/mineral/adhomai
- mineral_sparse = /turf/simulated/mineral/random/adhomai
- mineral_rich = /turf/simulated/mineral/random/high_chance/adhomai
- floor_type = /turf/simulated/floor/exoplanet/mineral/adhomai
- use_area = FALSE
-
-/datum/random_map/automata/cave_system/mountains/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly, var/do_not_apply, var/do_not_announce, var/never_be_priority = 0, var/used_area, var/datum/exoplanet_theme/_theme)
- if(_theme)
- planet_theme = _theme
- target_turf_type = world.turf
- floor_type = world.turf
- ..()
-
-/datum/random_map/automata/cave_system/mountains/get_additional_spawns(value, turf/T)
- planet_theme.on_turf_generation(T, use_area)
-
diff --git a/code/modules/overmap/exoplanets/themes/_theme.dm b/code/modules/overmap/exoplanets/themes/_theme.dm
new file mode 100644
index 00000000000..fb4a4b9a5da
--- /dev/null
+++ b/code/modules/overmap/exoplanets/themes/_theme.dm
@@ -0,0 +1,348 @@
+/datum/exoplanet_theme
+ var/name = "Default Theme"
+ /// List of /turf types that should be colored according to surface_color
+ var/list/surface_turfs = list()
+ /// Surface color applied to surface_turfs ; usually set by rock_colors on exoplanet
+ var/surface_color
+ /* Heightmap Generation
+ * Exoplanet themes work off of a series of 'heightmaps' generated from perlin noise.
+ * Essentially, perlin noise gives us a random value between 0 and 1 for every coordinate we plug into it
+ * If you apply thresholds to the data, e.g. "spawn a forest biome above 0.5", it can very quickly produce believable terrain
+ * The following are several required and optional parameters to tweak the generation data.
+ * For more information, see https://www.redblobgames.com/maps/terrain-from-noise/.
+ */
+
+ /// Exponent applied to the end result height value; values greater than 1 will preserve noise/height values near 1, while dragging the rest down near 0.
+ var/height_exponent = 1
+ /// Number of iterations (octaves) of perlin noise to use when generating the map. More iterations results in a smoother noise-map, but takes longer to generate.
+ var/height_iterations = 3
+ /// How 'zoomed in' we are to the noise map, with higher numbers generating smoother transitions and lower variability. 65 results in a relatively smooth noise map.
+ var/perlin_zoom = 65
+
+ /* Assoc list of possible /singleton/biomes, denoted by heat level and humidity
+ * possible_biomes => biome heat level: list(biome humidity => singleton/biome)
+ */
+ var/list/possible_biomes
+
+ /// Biome force-picked if height is over [mountain_threshold]. Set to null to disable.
+ var/mountain_biome = /singleton/biome/mountain
+ /// Height threshold for mountain generation; all turfs with a calculated height above this value will generate inside [mountain_biome]
+ var/mountain_threshold = 0.85
+
+ /* Assoc list of heat level defines to heat thresholds. Heat is taken as the inverse of height modified by distance from the equator (see get_heat)
+ * Biome is selected if the heat found is less than or equal to its correlated value. Values should scale to 1.0 as below.
+ * You do not need to use all biome levels, however any changes you make here should be reflected in [possible_biomes] and vice versa.
+ */
+ var/list/heat_levels = list(
+ BIOME_POLAR = 0.25,
+ BIOME_COOL = 0.5,
+ BIOME_WARM = 0.75,
+ BIOME_EQUATOR = 1.0
+ )
+ /// Assoc list of humidity level defines to humidity thresholds. Humidity is a seperate noise-map generated only for turfs ensured not to be a mountain.
+ var/list/humidity_levels = list(
+ BIOME_ARID = 0.25,
+ BIOME_SEMIARID = 0.5,
+ BIOME_SUBHUMID = 0.75,
+ BIOME_HUMID = 1.0
+ )
+ /* Ore generation
+ * These values reflect both the raw distribution of ores in the ground, and spawned minerals in rocks.
+ * The values are somewhat arbitrary, but the comments here should explain what values get what # of ore. You'll need to experiment.
+ * These values are divided by 4 and then clamped to (-0.5, 0.5); w.o the multiplication the "usable" range is roughly (-0.35, -0.27), so
+ * this gives us a bit more room to fine tune (at the cost of arbitrary numbers).
+ * Bear in mind that distribution will be affected by the mountain_threshold as well; these default values are picked to ensure a relatively similar amount
+ * of ores found in walls to the previous system on asteroids.
+ */
+ var/list/wall_ore_levels = list(
+ ORE_PLATINUM = 0.6,
+ ORE_DIAMOND = 0.6,
+ ORE_URANIUM = 0.7,
+ ORE_GOLD = 0.68,
+ ORE_SILVER = 0.7,
+ ORE_COAL = 0.9,
+ ORE_IRON = 0.92,
+ )
+
+ /// This is more straight forward. We use three noise maps and assign drillables based on that
+ var/list/ground_ore_levels = list(
+ SURFACE_ORES = list(
+ ORE_IRON = list(2, 4),
+ ORE_GOLD = list(0, 2),
+ ORE_SILVER = list(0, 2),
+ ORE_URANIUM = list(0, 2)
+ ),
+ RARE_ORES = list(
+ ORE_GOLD = list(1, 3),
+ ORE_SILVER = list(1, 3),
+ ORE_URANIUM = list(1, 3),
+ ORE_PLATINUM = list(1, 3)
+ ),
+ DEEP_ORES = list(
+ ORE_URANIUM = list(0, 2),
+ ORE_DIAMOND = list(0, 2),
+ ORE_PLATINUM = list(2, 4),
+ ORE_HYDROGEN = list(1, 3)
+ )
+ )
+
+ /// relatively speaking, the % (0-1) of turfs that will have resources generated in them
+ var/gnd_ore_coverage = 0.5
+ /// List of random seeds used for ore noise generation. Automatically generated on New() using wall_ore_levels.
+ var/list/ore_seeds
+ var/list/gnd_ore_seeds
+ /// Count of each ore present in mineral walls, used by cleanup() to ensure resource availability.
+ var/list/ore_counts
+
+ /// Assoc list of selected biomes to their random seed information, used in terrain generation
+ var/list/biome_seeds
+
+#define ORE_LEVEL_TO_DBP_RANGE(oval) (((oval) / 4) - 0.5)
+/datum/exoplanet_theme/New()
+ if(!length(wall_ore_levels))
+ return ..()
+
+ sortTim(wall_ore_levels, GLOBAL_PROC_REF(cmp_numeric_dsc), TRUE) // We want the rarest first
+ for(var/o in wall_ore_levels)
+ var/conv_level = max(-0.5, ORE_LEVEL_TO_DBP_RANGE(wall_ore_levels[o])) // seems like the noise range from DBP noise is (-0.5, 0.5) so we'll convert to that
+ LAZYSET(ore_seeds, o, rustg_dbp_generate("[rand(0, 50000)]", "16", "8", "[world.maxx]", "-0.5", "[conv_level]"))
+ LAZYSET(ore_counts, o, 0)
+
+ for(var/g in ground_ore_levels)
+ LAZYSET(gnd_ore_seeds, g, rustg_dbp_generate("[rand(0, 50000)]", "16", "8", "[world.maxx]", "-0.5", "[gnd_ore_coverage - 0.5]"))
+ LAZYSET(ore_counts, g, 0)
+
+/datum/exoplanet_theme/proc/before_map_generation(obj/effect/overmap/visitable/sector/exoplanet/E)
+ if(E.rock_colors)
+ surface_color = pick(E.rock_colors)
+
+/// This inverts our height value to get a heat value, and then maps that to a sine wave such that heat is preserved at the equator and reduced at the poles.
+#define GET_EQUATORIAL_HEAT(height, y_val) cos(TO_DEGREES(clamp(1 - height, 0, 1))) * sin(TO_DEGREES((y_val * M_PI) / 255))
+
+/* This will create a seed entry in biome_seeds to use in generation; we generate a unique "seed" for each type of generation in each biome.
+ * PURE_RANDOM and HEIGHT_MOD will simply copy over their probability and multiplier, respectively, from singleton/biome::generators
+ * POISSON_SAMPLE and BATCHED_NOISE will make calls to their respective rust-g functions, returning a string of 1s and 0s which correlates to X and Y coordinates
+ */
+#define SEED_TERRAIN(ftype) \
+ var/singleton/biome/SB = selected_biome; \
+ if(SB.generators[ftype][1] & ALWAYS_GEN) { LAZYSET(biome_seeds[SB], ftype, TRUE); } \
+ else if(SB.generators[ftype][1] & (PURE_RANDOM|HEIGHT_MOD)) { LAZYSET(biome_seeds[SB], ftype, SB.generators[ftype][2]); } \
+ else if(SB.generators[ftype][1] & POISSON_SAMPLE) { LAZYSET(biome_seeds[SB], ftype, rustg_noise_poisson_sample("[rand(1, 50000)]", "[world.maxx]", "[world.maxy]", "[SB.generators[ftype][2]]")); } \
+ else if(SB.generators[ftype][1] & BATCHED_NOISE) { LAZYSET(biome_seeds[SB], ftype, rustg_dbp_generate("[rand(1, 50000)]", "[SB.generators[ftype][3]]", "[SB.generators[ftype][4]]", "[world.maxx]", "-0.5", "[selected_biome.generators[ftype][2]]")); }
+
+// Constructs a dijkstra map of distances from origin using breadth-first search
+/obj/effect/overmap/visitable/sector/exoplanet/proc/build_heatmap(turf/origin)
+ if(!origin) return
+ var/Queue/frontier = new
+ frontier.enqueue(origin)
+ var/list/distance = list(origin = 0)
+ origin.maptext = "0"
+
+ while(length(frontier.contents))
+ var/turf/current = frontier.dequeue()
+ for (var/turf/N in RANGE_TURFS(1, current))
+ if(!(N in distance) && !N.density) // we don't care about turfs we've already seen, or ones we can't go through
+ frontier.enqueue(N)
+ distance[N] = 1 + distance[current]
+ N.maptext = "[distance[N]]"
+
+// In the name of not having 65,025 proc calls (and their overhead) for every turf, we instead get to have a massive monolith of a proc. Enjoy. I didn't.
+/datum/exoplanet_theme/proc/generate_map(obj/effect/overmap/visitable/sector/exoplanet/E, z_to_gen, min_x, min_y, max_x, max_y)
+ var/list/height_seeds = list()
+ for (var/i = 1 to height_iterations)
+ height_seeds += rand(0, 50000)
+ var/humidity_seed = rand(0, 50000)
+
+ for(var/turf/gen_turf in block(locate(min_x, min_y, z_to_gen), locate(max_x, max_y, z_to_gen)))
+ // Drift here gives us a bit of extra noise on the edges of biomes, to make it transition slightly more naturally
+ var/drift_x = (gen_turf.x + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)) / perlin_zoom
+ var/drift_y = (gen_turf.y + rand(-BIOME_RANDOM_SQUARE_DRIFT, BIOME_RANDOM_SQUARE_DRIFT)) / perlin_zoom
+
+ var/height = 0
+ var/height_divisor = 0
+ // Here we're creating 'octaves' by sampling different height maps at different zoom levels;
+ // [octave] gives us (1, 2, 4...), which we then use to sample additional maps at higher frequencies
+ // We then multiply by the inverse to reduce its weight relative to the initial octave
+ // [height_divisor] keeps track of the multiplications we've done so we can divide the ending height value to return to a sane range of (0, 1)
+ for(var/i in 1 to height_seeds.len)
+ var/octave = 2 ** (i - 1)
+ height += (1 / octave) * text2num(rustg_noise_get_at_coordinates("[height_seeds[i]]", "[octave * drift_x]", "[octave * drift_y]"))
+ height_divisor += (1 / octave)
+
+ height = (height / height_divisor) ** height_exponent
+
+ var/humidity = 0
+ var/heat = 0
+ var/singleton/biome/selected_biome
+ var/heat_level = BIOME_POLAR
+ var/humidity_level = BIOME_ARID
+
+ if((height < mountain_threshold) || !mountain_biome)
+ // We're only going to bother with secondary heatmaps and heat-level parsing if there's actually more than one level
+ if(length(humidity_levels) > 1)
+ humidity = text2num(rustg_noise_get_at_coordinates("[humidity_seed]", "[drift_x]", "[drift_y]"))
+ if(length(heat_levels) > 1)
+ heat = GET_EQUATORIAL_HEAT(height, gen_turf.y)
+
+ for(var/L in heat_levels)
+ if(heat <= heat_levels[L])
+ heat_level = L
+ break
+
+ for(var/L in humidity_levels)
+ if(humidity <= humidity_levels[L])
+ humidity_level = L
+ break
+
+ selected_biome = GET_SINGLETON(possible_biomes[heat_level][humidity_level])
+ else
+ selected_biome = GET_SINGLETON(mountain_biome)
+
+ LAZYDISTINCTADD(biome_seeds, selected_biome)
+ LAZYINITLIST(biome_seeds[selected_biome])
+
+ // Converting (255 * 255) coordinates to a 65025 character string; each block of 255 is one Y coordinate, and what's left over is our X coordinate
+ var/coord_to_str = (world.maxx * gen_turf.y) + gen_turf.x
+ var/turf_type_to_gen
+
+ // Code duplication for the sake of clarity over a define; this is the main generation function. PLANET_TURF is a special case;
+ // We don't always have PLANET_TURF specified as a generator (in fact we usually don't), so we'll just defer to [selected_biome.turf_type] in that case
+ if(PLANET_TURF in selected_biome.generators)
+ if(!LAZYISIN(biome_seeds[selected_biome], PLANET_TURF))
+ SEED_TERRAIN(PLANET_TURF)
+ var/alt_turf = FALSE
+ switch(selected_biome.generators[PLANET_TURF][1])
+ if(ALWAYS_GEN)
+ alt_turf = TRUE
+ if(PURE_RANDOM)
+ alt_turf = prob(biome_seeds[selected_biome][PLANET_TURF])
+ if(HEIGHT_MOD)
+ var/new_heat_level
+ var/new_humid_level
+ for(var/L in heat_levels)
+ if((heat * biome_seeds[selected_biome][PLANET_TURF]) <= heat_levels[L])
+ new_heat_level = L
+ break
+ for(var/L in humidity_levels)
+ if((humidity * biome_seeds[selected_biome][PLANET_TURF]) <= humidity_levels[L])
+ new_humid_level = L
+ break
+ alt_turf = ((heat_level == new_heat_level) && (humidity_level == new_humid_level))
+ if(POISSON_SAMPLE)
+ alt_turf = biome_seeds[selected_biome][PLANET_TURF][coord_to_str] == "1"
+ if(BATCHED_NOISE)
+ alt_turf = biome_seeds[selected_biome][PLANET_TURF][coord_to_str] == "1"
+ if(alt_turf)
+ turf_type_to_gen = pickweight(selected_biome.spawn_types[PLANET_TURF])
+
+ if(!ispath(turf_type_to_gen, /turf))
+ turf_type_to_gen = selected_biome.turf_type
+
+ gen_turf.ChangeTurf(turf_type_to_gen, mapload = TRUE)
+ if(istype(selected_biome, mountain_biome))
+ for(var/ore in ore_seeds)
+ if(text2num(ore_seeds[ore][coord_to_str]))
+ var/turf/simulated/mineral/M = gen_turf
+ M.change_mineral(ore, TRUE)
+ ore_counts[ore]++
+ break
+
+ if(gen_turf.has_resources)
+ var/ground_resources_roll
+ for(var/ore in gnd_ore_seeds)
+ if(text2num(gnd_ore_seeds[ore][coord_to_str]))
+ ore_counts[ore]++
+ ground_resources_roll = ore
+ break
+ gen_turf.resources = list()
+ gen_turf.resources[ORE_SAND] = rand(3, 5)
+ gen_turf.resources[ORE_COAL] = rand(3, 5)
+ if(ground_resources_roll)
+ for(var/OT in ground_ore_levels[ground_resources_roll])
+ var/rand_vals = ground_ore_levels[ground_resources_roll][OT]
+ gen_turf.resources[OT] = rand(rand_vals[1], rand_vals[2])
+
+ if(gen_turf.density) // No need to check flora/fauna/grass if we're a wall
+ continue
+
+ if(PLANET_TURF in selected_biome.generators)
+ if((turf_type_to_gen != selected_biome.turf_type) && (PLANET_TURF in selected_biome.exclusive_generators))
+ continue // snowflake check since the terrain gen code below won't look for PLANET_TURF, and we only want to stop gen for non-standard turf types
+
+ /* Main terrain generation function. Once we have our turf and we know we're not dense, we can loop through our generators as noted in our biome file
+ * Each generators definition follows the format: generators = list(GENERATOR_NAME = list(GENERATOR_TYPE, PARAMS...))
+ * Different generation types have different parameters; ALWAYS_GEN has none, since it's always generating if valid.
+ * This is essentially just a switch that goes through each generator, checks if it returns true for this tile, and if so, picks something from the weighted spawn_types list.
+ */
+ for(var/to_gen in selected_biome.generators)
+ if(to_gen == PLANET_TURF)
+ continue // we dealt with turfs already
+ if(!LAZYISIN(biome_seeds[selected_biome], to_gen))
+ SEED_TERRAIN(to_gen)
+ var/check = FALSE
+ switch(selected_biome.generators[to_gen][1])
+ if(ALWAYS_GEN)
+ check = TRUE
+ if(PURE_RANDOM)
+ check = prob(biome_seeds[selected_biome][to_gen])
+ if(HEIGHT_MOD)
+ var/new_heat_level
+ var/new_humid_level
+ // Here we apply the HEIGHT_MOD to heat and humidity, and see if they still meet the same level.
+ for(var/L in heat_levels)
+ if((heat * biome_seeds[selected_biome][to_gen]) <= heat_levels[L])
+ new_heat_level = L
+ break
+ for(var/L in humidity_levels)
+ if((humidity * biome_seeds[selected_biome][to_gen]) <= humidity_levels[L])
+ new_humid_level = L
+ break
+ check = ((heat_level == new_heat_level) && (humidity_level == new_humid_level))
+ if(POISSON_SAMPLE)
+ check = biome_seeds[selected_biome][to_gen][coord_to_str] == "1"
+ if(BATCHED_NOISE)
+ check = biome_seeds[selected_biome][to_gen][coord_to_str] == "1"
+ if(!check)
+ continue
+ var/obj_path = pickweight(selected_biome.spawn_types[to_gen])
+ if(obj_path)
+ new obj_path(gen_turf)
+ if(to_gen in selected_biome.exclusive_generators)
+ break // we break out of the generation loop for this turf if we come across an 'exclusive generator'
+
+ CHECK_TICK
+
+/datum/exoplanet_theme/proc/on_turf_generation(turf/T, area/use_area)
+ if(use_area && istype(T.loc, world.area))
+ ChangeArea(T, use_area) // Switch our generated turfs from world.area (space) to our chosen exoplanet area
+ if(surface_color && is_type_in_list(T, surface_turfs))
+ T.color = surface_color
+
+ var/turf/simulated/mineral/M = T
+ if(use_area && istype(M))
+ M.mined_turf = use_area.base_turf
+
+/datum/exoplanet_theme/proc/cleanup(obj/effect/overmap/visitable/sector/exoplanet/E, z_to_check, min_x, min_y, max_x, max_y)
+ if(!LAZYLEN(ore_counts) || !LAZYLEN(wall_ore_levels))
+ return
+
+ for(var/o in ore_counts)
+ if(ore_counts[o] < 100) // Bit of a magic number but we just want to make sure there's a little bit of every ore
+ var/conv_level = max(-0.5, ORE_LEVEL_TO_DBP_RANGE(wall_ore_levels[o])) // seems like the noise range from DBP noise is (-0.5, 0.5) so we'll convert to that
+ LAZYSET(ore_seeds, o, rustg_dbp_generate("[rand(0, 50000)]", "16", "8", "[world.maxx]", "-0.5", "[conv_level]"))
+ else
+ LAZYREMOVE(ore_seeds, o)
+
+ if(!length(ore_seeds))
+ return
+
+ for(var/turf/simulated/mineral/M in block(locate(min_x, min_y, z_to_check), locate(max_x, max_y, z_to_check)))
+ if(!istype(M) || M.mineral)
+ continue
+ var/coord_to_str = (world.maxx * M.y) + M.x
+ for(var/ore in ore_seeds)
+ if(text2num(ore_seeds[ore][coord_to_str]))
+ M.mineral = ore_data[ore]
+ M.UpdateMineral() // It's already a mineral turf, so we can avoid changeturf here
+
+/datum/exoplanet_theme/proc/get_planet_image_extra()
diff --git a/code/modules/overmap/exoplanets/themes/barren.dm b/code/modules/overmap/exoplanets/themes/barren.dm
new file mode 100644
index 00000000000..94e71fa9edc
--- /dev/null
+++ b/code/modules/overmap/exoplanets/themes/barren.dm
@@ -0,0 +1,83 @@
+/datum/exoplanet_theme/barren
+ name = "Barren"
+ surface_turfs = list(
+ /turf/simulated/mineral,
+ /turf/simulated/floor/exoplanet/barren
+ )
+ possible_biomes = list(
+ BIOME_POLAR = list(
+ BIOME_ARID = /singleton/biome/barren
+ )
+ )
+
+ mountain_threshold = 0.6
+
+ heat_levels = list(
+ BIOME_POLAR = 1.0
+ )
+
+ humidity_levels = list(
+ BIOME_ARID = 1.0
+ )
+
+/datum/exoplanet_theme/barren/raskara
+ name = "Raskara"
+ surface_turfs = list(
+ /turf/simulated/mineral,
+ /turf/simulated/floor/exoplanet/barren/raskara
+ )
+ possible_biomes = list(
+ BIOME_POLAR = list(
+ BIOME_ARID = /singleton/biome/barren/raskara
+ )
+ )
+
+/datum/exoplanet_theme/barren/asteroid
+ name = "Asteroid"
+ mountain_threshold = 0.5
+ perlin_zoom = 21
+ surface_turfs = list(
+ /turf/simulated/mineral,
+ /turf/unsimulated/floor/asteroid/ash
+ )
+
+ possible_biomes = list(
+ BIOME_POLAR = list(
+ BIOME_ARID = /singleton/biome/barren/asteroid
+ )
+ )
+
+/datum/exoplanet_theme/barren/asteroid/phoron
+ name = "Romanovich Asteroid"
+ wall_ore_levels = list(
+ ORE_PHORON = 0.7,
+ ORE_PLATINUM = 0.6,
+ ORE_DIAMOND = 0.6,
+ ORE_URANIUM = 0.7,
+ ORE_GOLD = 0.68,
+ ORE_SILVER = 0.7,
+ ORE_COAL = 0.9,
+ ORE_IRON = 0.92,
+ )
+ ground_ore_levels = list(
+ SURFACE_ORES = list(
+ ORE_IRON = list(2, 4),
+ ORE_GOLD = list(0, 2),
+ ORE_SILVER = list(0, 2),
+ ORE_URANIUM = list(0, 2)
+ ),
+ RARE_ORES = list(
+ ORE_GOLD = list(1, 3),
+ ORE_SILVER = list(1, 3),
+ ORE_URANIUM = list(1, 3),
+ ORE_PLATINUM = list(1, 3),
+ ORE_PHORON = list(0, 2)
+ ),
+ DEEP_ORES = list(
+ ORE_URANIUM = list(0, 2),
+ ORE_DIAMOND = list(0, 2),
+ ORE_PLATINUM = list(2, 4),
+ ORE_HYDROGEN = list(1, 3),
+ ORE_PHORON = list(0, 2)
+ )
+ )
diff --git a/code/modules/overmap/exoplanets/themes/crystal.dm b/code/modules/overmap/exoplanets/themes/crystal.dm
new file mode 100644
index 00000000000..2aac8493f35
--- /dev/null
+++ b/code/modules/overmap/exoplanets/themes/crystal.dm
@@ -0,0 +1,22 @@
+/datum/exoplanet_theme/crystal
+ name = "Crystalline"
+ surface_turfs = list(
+ /turf/simulated/mineral
+ )
+
+ perlin_zoom = 21
+ mountain_threshold = 0.5
+
+ heat_levels = list(
+ BIOME_EQUATOR = 1.0
+ )
+
+ humidity_levels = list(
+ BIOME_ARID = 1.0
+ )
+
+ possible_biomes = list(
+ BIOME_EQUATOR = list(
+ BIOME_ARID = /singleton/biome/crystal
+ )
+ )
diff --git a/code/modules/overmap/exoplanets/themes/desert.dm b/code/modules/overmap/exoplanets/themes/desert.dm
new file mode 100644
index 00000000000..3a693c9745e
--- /dev/null
+++ b/code/modules/overmap/exoplanets/themes/desert.dm
@@ -0,0 +1,55 @@
+/datum/exoplanet_theme/desert
+ name = "Desert"
+ surface_turfs = list(
+ /turf/simulated/mineral
+ )
+ possible_biomes = list(
+ BIOME_POLAR = list(
+ BIOME_ARID = /singleton/biome/desert/scrub,
+ BIOME_SEMIARID = /singleton/biome/desert/thorn,
+ BIOME_SUBHUMID = /singleton/biome/desert/thorn,
+ BIOME_HUMID = /singleton/biome/desert/scrub
+ ),
+ BIOME_COOL = list(
+ BIOME_ARID = /singleton/biome/desert,
+ BIOME_SEMIARID = /singleton/biome/desert/scrub,
+ BIOME_SUBHUMID = /singleton/biome/desert/thorn,
+ BIOME_HUMID = /singleton/biome/desert/thorn
+ ),
+ BIOME_WARM = list(
+ BIOME_ARID = /singleton/biome/desert,
+ BIOME_SEMIARID = /singleton/biome/desert,
+ BIOME_SUBHUMID = /singleton/biome/desert/scrub,
+ BIOME_HUMID = /singleton/biome/desert/thorn
+ ),
+ BIOME_EQUATOR = list(
+ BIOME_ARID = /singleton/biome/desert,
+ BIOME_SEMIARID = /singleton/biome/desert,
+ BIOME_SUBHUMID = /singleton/biome/desert,
+ BIOME_HUMID = /singleton/biome/desert/scrub
+ )
+ )
+
+ heat_levels = list(
+ BIOME_POLAR = 0.1,
+ BIOME_COOL = 0.3,
+ BIOME_WARM = 0.5,
+ BIOME_EQUATOR = 1.0
+ )
+
+ humidity_levels = list(
+ BIOME_ARID = 0.6,
+ BIOME_SEMIARID = 0.8,
+ BIOME_SUBHUMID = 0.9,
+ BIOME_HUMID = 1.0
+ )
+
+/datum/exoplanet_theme/desert/savannah
+ name = "Savannah"
+
+ humidity_levels = list(
+ BIOME_ARID = 0.3,
+ BIOME_SEMIARID = 0.6,
+ BIOME_SUBHUMID = 0.8,
+ BIOME_HUMID = 1.0
+ )
diff --git a/code/modules/overmap/exoplanets/themes/grass.dm b/code/modules/overmap/exoplanets/themes/grass.dm
new file mode 100644
index 00000000000..f365851ee6d
--- /dev/null
+++ b/code/modules/overmap/exoplanets/themes/grass.dm
@@ -0,0 +1,65 @@
+/datum/exoplanet_theme/grass
+ name = "Grasslands" // Not gm_flatgrass, but pretty close
+ surface_turfs = list(
+ /turf/simulated/floor/exoplanet/grass,
+ /turf/simulated/mineral
+ )
+ mountain_threshold = 0.9
+ possible_biomes = list(
+ BIOME_COOL = list(
+ BIOME_ARID = /singleton/biome/grass/chaparral,
+ BIOME_SEMIARID = /singleton/biome/grass/forest,
+ BIOME_SUBHUMID = /singleton/biome/grass/forest
+ ),
+ BIOME_WARM = list(
+ BIOME_ARID = /singleton/biome/grass/chaparral,
+ BIOME_SEMIARID = /singleton/biome/grass,
+ BIOME_SUBHUMID = /singleton/biome/grass/riverside
+ ),
+ BIOME_EQUATOR = list(
+ BIOME_ARID = /singleton/biome/grass,
+ BIOME_SEMIARID = /singleton/biome/grass/riverside,
+ BIOME_SUBHUMID = /singleton/biome/grass/riverside
+ )
+ )
+
+ heat_levels = list(
+ BIOME_COOL = 0.4,
+ BIOME_WARM = 0.8,
+ BIOME_EQUATOR = 1.0
+ )
+
+ humidity_levels = list(
+ BIOME_ARID = 0.2,
+ BIOME_SEMIARID = 0.5,
+ BIOME_SUBHUMID = 1.0
+ )
+
+/datum/exoplanet_theme/grass/before_map_generation(obj/effect/overmap/visitable/sector/exoplanet/E)
+ . = ..()
+ surface_color = E.grass_color
+
+/datum/exoplanet_theme/grass/marsh
+ name = "Fungal Marsh"
+ surface_turfs = list(
+ /turf/simulated/mineral
+ )
+ possible_biomes = list(
+ BIOME_WARM = list(
+ BIOME_SUBHUMID = /singleton/biome/marsh,
+ BIOME_HUMID = /singleton/biome/marsh/forest
+ ),
+ BIOME_EQUATOR = list(
+ BIOME_SUBHUMID = /singleton/biome/marsh,
+ BIOME_HUMID = /singleton/biome/marsh/forest
+ )
+
+ )
+ heat_levels = list(
+ BIOME_WARM = 0.5,
+ BIOME_EQUATOR = 1.0
+ )
+ humidity_levels = list(
+ BIOME_SUBHUMID = 0.4,
+ BIOME_HUMID = 1.0
+ )
diff --git a/code/modules/overmap/exoplanets/themes/jungle.dm b/code/modules/overmap/exoplanets/themes/jungle.dm
new file mode 100644
index 00000000000..a2c7f6a5884
--- /dev/null
+++ b/code/modules/overmap/exoplanets/themes/jungle.dm
@@ -0,0 +1,36 @@
+/datum/exoplanet_theme/jungle
+ // Welcome to the
+ name = "Jungle"
+ surface_turfs = list(
+ /turf/simulated/mineral
+ )
+ mountain_threshold = 0.8
+ possible_biomes = list(
+ BIOME_COOL = list(
+ BIOME_ARID = /singleton/biome/water,
+ BIOME_SEMIARID = /singleton/biome/jungle/clearing,
+ BIOME_SUBHUMID = /singleton/biome/jungle
+ ),
+ BIOME_WARM = list(
+ BIOME_ARID = /singleton/biome/jungle/clearing,
+ BIOME_SEMIARID = /singleton/biome/jungle,
+ BIOME_SUBHUMID = /singleton/biome/jungle/dense
+ ),
+ BIOME_EQUATOR = list(
+ BIOME_ARID = /singleton/biome/jungle,
+ BIOME_SEMIARID = /singleton/biome/jungle/dense,
+ BIOME_SUBHUMID = /singleton/biome/jungle/dense
+ )
+ )
+
+ heat_levels = list(
+ BIOME_COOL = 0.3,
+ BIOME_WARM = 0.6,
+ BIOME_EQUATOR = 1.0
+ )
+
+ humidity_levels = list(
+ BIOME_ARID = 0.3,
+ BIOME_SEMIARID = 0.6,
+ BIOME_SUBHUMID = 1.0
+ )
diff --git a/code/modules/overmap/exoplanets/themes/lava.dm b/code/modules/overmap/exoplanets/themes/lava.dm
new file mode 100644
index 00000000000..2472b7a68f2
--- /dev/null
+++ b/code/modules/overmap/exoplanets/themes/lava.dm
@@ -0,0 +1,26 @@
+/datum/exoplanet_theme/volcanic
+ name = "Volcanic"
+ surface_turfs = list(
+ /turf/simulated/mineral
+ )
+
+ perlin_zoom = 21
+ mountain_threshold = 0.6
+
+ heat_levels = list(
+ BIOME_POLAR = 0.3,
+ BIOME_EQUATOR = 1.0
+ )
+
+ humidity_levels = list(
+ BIOME_ARID = 1.0
+ )
+
+ possible_biomes = list(
+ BIOME_POLAR = list(
+ BIOME_ARID = /singleton/biome/lava
+ ),
+ BIOME_EQUATOR = list(
+ BIOME_ARID = /singleton/biome/barren/asteroid/basalt
+ )
+ )
diff --git a/code/modules/overmap/exoplanets/themes/snow.dm b/code/modules/overmap/exoplanets/themes/snow.dm
new file mode 100644
index 00000000000..eb1e44bdc6a
--- /dev/null
+++ b/code/modules/overmap/exoplanets/themes/snow.dm
@@ -0,0 +1,62 @@
+/datum/exoplanet_theme/snow
+ name = "Boreal Forest"
+ surface_turfs = list(
+ /turf/simulated/mineral
+ )
+ possible_biomes = list(
+ BIOME_POLAR = list(
+ BIOME_ARID = /singleton/biome/water/ice,
+ BIOME_SEMIARID = /singleton/biome/snow
+ ),
+ BIOME_COOL = list(
+ BIOME_ARID = /singleton/biome/snow,
+ BIOME_SEMIARID = /singleton/biome/snow/forest
+ )
+ )
+
+ heat_levels = list(
+ BIOME_POLAR = 0.3,
+ BIOME_COOL = 1.0,
+ )
+
+ humidity_levels = list(
+ BIOME_ARID = 0.7,
+ BIOME_SEMIARID = 1.0
+ )
+
+/datum/exoplanet_theme/snow/tundra
+ name = "Frozen Tundra"
+ heat_levels = list(
+ BIOME_POLAR = 0.7,
+ BIOME_COOL = 1.0
+ )
+ mountain_threshold = 0.6
+
+/datum/exoplanet_theme/snow/adhomai
+ name = "Adhomai"
+ mountain_threshold = 0.6
+ mountain_biome = /singleton/biome/mountain/adhomai
+ possible_biomes = list(
+ BIOME_POLAR = list(
+ BIOME_ARID = /singleton/biome/water/ice,
+ BIOME_SEMIARID = /singleton/biome/snow/adhomai
+ ),
+ BIOME_COOL = list(
+ BIOME_ARID = /singleton/biome/snow/adhomai,
+ BIOME_SEMIARID = /singleton/biome/snow/forest/adhomai
+ )
+ )
+
+/datum/exoplanet_theme/snow/tundra/adhomai
+ name = "Adhomai North Pole"
+ mountain_biome = /singleton/biome/mountain/adhomai
+ possible_biomes = list(
+ BIOME_POLAR = list(
+ BIOME_ARID = /singleton/biome/water/ice/polar,
+ BIOME_SEMIARID = /singleton/biome/snow/adhomai/polar
+ ),
+ BIOME_COOL = list(
+ BIOME_ARID = /singleton/biome/snow/adhomai/polar,
+ BIOME_SEMIARID = /singleton/biome/snow/adhomai/polar
+ )
+ )
diff --git a/code/modules/shuttles/landmarks.dm b/code/modules/shuttles/landmarks.dm
index eb599321187..74027be786b 100644
--- a/code/modules/shuttles/landmarks.dm
+++ b/code/modules/shuttles/landmarks.dm
@@ -108,9 +108,11 @@
var/radius = LANDING_ZONE_RADIUS
/obj/effect/shuttle_landmark/automatic/clearing/LateInitialize()
- for(var/turf/T in range(radius, src))
+ for(var/turf/T in RANGE_TURFS(LANDING_ZONE_RADIUS, src))
if(T.density)
T.ChangeTurf(get_base_turf_by_area(T))
+ for(var/obj/structure/S in T)
+ qdel(S)
..()
/obj/item/device/spaceflare
diff --git a/html/changelogs/johnwildkins-exogen.yml b/html/changelogs/johnwildkins-exogen.yml
new file mode 100644
index 00000000000..352fa7e5e2f
--- /dev/null
+++ b/html/changelogs/johnwildkins-exogen.yml
@@ -0,0 +1,12 @@
+author: JohnWildkins
+
+delete-after: True
+
+changes:
+ - rscadd: "Complete overhaul of exoplanet generation, with updated themes for asteroids, barren, desert, grove, and lava planets."
+ - rscadd: "Implemented grass and snow planet generation."
+ - rscadd: "Added two new planet types: crystalline and swampland/marshland."
+ - tweak: "In general, mineral walls are far less frequent on mineral poor worlds, namely grove/grass/snow planets (except Adhomai)."
+ - backend: "Updated rust-g to latest version, including new methods of noise generation."
+ - backend: "Replaced the random_map system with exoplanet themes and biomes, all now located within overmap/exoplanets."
+ - tweak: "Several performance tweaks in ChangeTurf and turf init/destroy to increase mapgen performance."
diff --git a/icons/obj/flora/crystal_trees.dmi b/icons/obj/flora/crystal_trees.dmi
new file mode 100644
index 00000000000..b9e2fcfae2c
Binary files /dev/null and b/icons/obj/flora/crystal_trees.dmi differ
diff --git a/icons/obj/flora/desert_cactus_trees.dmi b/icons/obj/flora/desert_cactus_trees.dmi
new file mode 100644
index 00000000000..b3bb0c68015
Binary files /dev/null and b/icons/obj/flora/desert_cactus_trees.dmi differ
diff --git a/icons/obj/flora/desertflora.dmi b/icons/obj/flora/desertflora.dmi
new file mode 100644
index 00000000000..20ef81d1d86
Binary files /dev/null and b/icons/obj/flora/desertflora.dmi differ
diff --git a/icons/obj/flora/fungalflora.dmi b/icons/obj/flora/fungalflora.dmi
new file mode 100644
index 00000000000..baf46b83994
Binary files /dev/null and b/icons/obj/flora/fungalflora.dmi differ
diff --git a/icons/obj/flora/fungaltrees.dmi b/icons/obj/flora/fungaltrees.dmi
new file mode 100644
index 00000000000..d9e41a24749
Binary files /dev/null and b/icons/obj/flora/fungaltrees.dmi differ
diff --git a/icons/obj/flora/snowrocks.dmi b/icons/obj/flora/snowrocks.dmi
new file mode 100644
index 00000000000..dd4c1d7a664
Binary files /dev/null and b/icons/obj/flora/snowrocks.dmi differ
diff --git a/icons/turf/crystal.dmi b/icons/turf/crystal.dmi
new file mode 100644
index 00000000000..206c06dccbf
Binary files /dev/null and b/icons/turf/crystal.dmi differ
diff --git a/icons/turf/decals/sand64x32.dmi b/icons/turf/decals/sand64x32.dmi
new file mode 100644
index 00000000000..29e964dfb3a
Binary files /dev/null and b/icons/turf/decals/sand64x32.dmi differ
diff --git a/icons/turf/desert.dmi b/icons/turf/desert.dmi
index 439f5630f06..289056c6bf8 100644
Binary files a/icons/turf/desert.dmi and b/icons/turf/desert.dmi differ
diff --git a/icons/turf/fungal_marsh.dmi b/icons/turf/fungal_marsh.dmi
new file mode 100644
index 00000000000..8013687cbb8
Binary files /dev/null and b/icons/turf/fungal_marsh.dmi differ
diff --git a/librust_g.so b/librust_g.so
index fa052896435..1dc98014323 100644
Binary files a/librust_g.so and b/librust_g.so differ
diff --git a/maps/random_ruins/exoplanets/adhomai/adhomai_sole_rock_nomad.dm b/maps/random_ruins/exoplanets/adhomai/adhomai_sole_rock_nomad.dm
index a8bb6d24ad5..8b81e912582 100644
--- a/maps/random_ruins/exoplanets/adhomai/adhomai_sole_rock_nomad.dm
+++ b/maps/random_ruins/exoplanets/adhomai/adhomai_sole_rock_nomad.dm
@@ -5,6 +5,7 @@
spawn_weight = 1
spawn_cost = 2
+ template_flags = TEMPLATE_FLAG_NO_RUINS|TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED
sectors = list(SECTOR_SRANDMARR)
template_flags = TEMPLATE_FLAG_NO_RUINS|TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED
suffixes = list("adhomai/adhomai_sole_rock_nomad.dmm")
diff --git a/rust_g.dll b/rust_g.dll
index ea6678faf74..9393f4ae5eb 100644
Binary files a/rust_g.dll and b/rust_g.dll differ