Exoplanet Overhaul: The Shape of Things to Come (#16216)

* the end of the beginning

* SPEED

* SPEED

* we real speed

* fix ore gen

* re-organize exoplanet stuff

* reorg and rename defines, fix ores

* Everything Else

* 1.2.0+a3 rust_g

* fix merge

* get rid of noise maps

* fix adhomai, delete random maps

* make adhomai poggers or something idk

* debug

* crystal planet, misc bugfixes

* fixes

* log

* change mineral gen to make adhomai work

* try this

* huh

* huhw

* rust_g 1.2.0+a4

* port adhomai changes to correct file

* fix for rock nomad

* bugfixes
This commit is contained in:
Wildkins
2023-04-25 13:48:54 +00:00
committed by GitHub
parent 1cdda204ab
commit 9f1bdd2847
92 changed files with 2361 additions and 1216 deletions
@@ -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
@@ -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
@@ -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()
@@ -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
)
)
@@ -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
)
)
@@ -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,
)
)
@@ -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)
)
@@ -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
)
)
@@ -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)
)
@@ -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
@@ -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
@@ -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
..()
@@ -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("<span class='notice'>[user] fills \the [RG] from \the [src].</span>","<span class='notice'>You fill \the [RG] from \the [src].</span>")
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
@@ -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)
@@ -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)]"
. = ..()
@@ -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
..()
@@ -0,0 +1,47 @@
//tree
/obj/structure/flora/tree/adhomai
icon = 'icons/obj/flora/adhomai_trees.dmi'
icon_state = "tree1"
pixel_x = -32
stumptype = /obj/structure/flora/stump/adhomai
/obj/structure/flora/tree/adhomai/Initialize(mapload)
. = ..()
icon_state = "tree[rand(1, 12)]"
/obj/structure/flora/stump/adhomai
icon = 'icons/obj/flora/adhomai_trees.dmi'
icon_state = "stump"
pixel_x = -32
//bushes
/obj/structure/flora/bush/adhomai
icon = 'icons/obj/flora/adhomai_flora.dmi'
icon_state = "bush1"
anchored = 1
/obj/structure/flora/bush/adhomai/Initialize(mapload)
. = ..()
icon_state = "bush[rand(1, 7)]"
//grass
/obj/structure/flora/grass/adhomai
icon = 'icons/obj/flora/adhomai_flora.dmi'
icon_state = "grass1"
/obj/structure/flora/grass/adhomai/Initialize(mapload)
. = ..()
icon_state = "grass[rand(1, 4)]"
//rock
/obj/structure/flora/rock/adhomai
icon = 'icons/obj/flora/adhomai_flora.dmi'
icon_state = "rock1"
/obj/structure/flora/rock/adhomai/Initialize(mapload)
. = ..()
icon_state = "rock[rand(1, 5)]"
@@ -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)]"
. = ..()
@@ -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)
. = ..()
@@ -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)]"
@@ -0,0 +1,52 @@
//tree
/obj/structure/flora/tree/grove
icon = 'icons/obj/flora/grove_trees.dmi'
icon_state = "grove_tree1"
/obj/structure/flora/tree/grove/New()
..()
icon_state = "grove_tree[rand(1, 6)]"
//bushes
/obj/structure/flora/bush/grove
icon = 'icons/obj/flora/groveflora.dmi'
icon_state = "grove_bush1"
anchored = 1
/obj/structure/flora/bush/grove/New()
..()
icon_state = "grove_bush[rand(1, 4)]"
//clutter
/obj/structure/flora/clutter
name = "clutter"
icon = 'icons/obj/flora/groveflora.dmi'
icon_state = "grove_clutter1"
anchored = 1
/obj/structure/flora/clutter/New()
..()
icon_state = "grove_clutter[rand(1, 9)]"
//stalks
/obj/structure/flora/stalks
name = "stalks"
icon = 'icons/obj/flora/groveflora.dmi'
icon_state = "grove_stalks"
anchored = 1
/obj/structure/flora/stalks/New()
..()
icon_state = "grove_stalks[rand(1, 2)]"
//bamboo
/obj/structure/flora/bamboo
name = "bamboo stalks"
icon = 'icons/obj/flora/groveflora.dmi'
icon_state = "grove_bamboo"
anchored = 1
/obj/structure/flora/stalks/New()
..()
icon_state = "grove_bamboo[rand(1, 3)]"
@@ -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)
@@ -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)]"
. = ..()
@@ -0,0 +1,128 @@
/obj/structure/flora/pottedplant
name = "potted plant"
desc = "A potted plant."
icon = 'icons/obj/plants.dmi'
icon_state = "plant-26"
anchored = FALSE
density = FALSE
var/dead = FALSE
var/obj/item/stored_item
/obj/structure/flora/pottedplant/Destroy()
QDEL_NULL(stored_item)
return ..()
/obj/structure/flora/pottedplant/proc/death()
if(!dead)
icon_state = "plant-dead"
name = "dead [name]"
desc = "A dead potted plant."
dead = TRUE
//No complex interactions, just make them fragile
/obj/structure/flora/pottedplant/ex_act(var/severity = 2.0)
death()
return ..()
/obj/structure/flora/pottedplant/fire_act()
death()
return ..()
/obj/structure/flora/pottedplant/attackby(obj/item/W, mob/user)
if(!ishuman(user))
return
if(istype(W, /obj/item/holder))
return //no hiding mobs in there
user.visible_message("[user] begins digging around inside of \the [src].", "You begin digging around in \the [src], trying to hide \the [W].")
playsound(loc, 'sound/effects/plantshake.ogg', 50, 1)
if(do_after(user, 20, act_target = src))
if(!stored_item)
if(W.w_class <= ITEMSIZE_NORMAL)
user.drop_from_inventory(W,src)
stored_item = W
to_chat(user,"<span class='notice'>You hide \the [W] in [src].</span>")
return
else
to_chat(user,"<span class='notice'>\The [W] can't be hidden in [src], it's too big.</span>")
return
else
to_chat(user,"<span class='notice'>There is something hidden in [src].</span>")
return
return ..()
/obj/structure/flora/pottedplant/attack_hand(mob/user)
user.visible_message("[user] begins digging around inside of \the [src].", "You begin digging around in \the [src], searching it.")
playsound(loc, 'sound/effects/plantshake.ogg', 50, 1)
if(do_after(user, 40, act_target = src))
if(!stored_item)
to_chat(user,"<span class='notice'>There is nothing hidden in [src].</span>")
else
if(istype(stored_item, /obj/item/device/paicard))
stored_item.forceMove(src.loc)
to_chat(user,"<span class='notice'>You reveal \the [stored_item] from [src].</span>")
else
user.put_in_hands(stored_item)
to_chat(user,"<span class='notice'>You take \the [stored_item] from [src].</span>")
stored_item = null
/obj/structure/flora/pottedplant/bullet_act(var/obj/item/projectile/Proj)
if (prob(Proj.damage*2))
death()
return 1
return ..()
// Added random icon selection for potted plants.
// It was silly they always used the same sprite when we have 26 sprites of them in the icon file.
/obj/structure/flora/pottedplant/random/New()
..()
var/number = rand(1,36)
if (number == 36)
if (prob(90)) // Make the weird one rarer
number = rand(1,35)
else if(!desc)
desc = "A half-sentient plant borne from a mishap in a Zeng-Hu genetics lab."
if(!desc)
switch(number) //Wezzy's cool new plant description code. Special thanks to Sindorman.
if(3)
desc = "A bouquet of Bieselite flora."
if(4)
desc = "A bamboo plant. Used widely in Japanese crafts."
if(5)
desc = "Some kind of fern."
if(7)
desc = "A reedy plant mostly used for decoration in Skrell homes, admired for its luxuriant stalks."
if(9)
desc = "A fleshy cave dwelling plant with huge nodules for flowers."
if(9)
desc = "A scrubby cactus adapted to the Moghes deserts."
if(13)
desc = "A hardy succulent adapted to the Moghes deserts."
if(14)
desc = "That's a huge flower. Previously, the petals would be used in dyes for unathi garb. Now it's more of a decorative plant."
if(15)
desc = "A pitiful pot of stubby flowers."
if(18)
desc = "An orchid plant. As beautiful as it is delicate."
if(19)
desc = "A ropey, aquatic plant with crystaline flowers."
if(20)
desc = "A bioluminescent half-plant half-fungus hybrid. Said to come from Sedantis I."
if(22)
desc = "A cone shrub. Sadly doesn't come from Coney Island."
if(26)
desc = "A bulrush. Commonly referred to as cattail."
if(27)
desc = "A rose bush. Don't prick yourself."
if(32)
desc = "A woody shrub."
if(33)
desc = "A woody shrub. Seems to be in need of watering."
if(34)
desc = "A woody shrub. This one seems to be in bloom. It's just like one of my japanese animes."
else
desc = "Just your common, everyday houseplant."
if (number < 10)
number = "0[number]"
icon_state = "plant-[number]"
@@ -0,0 +1,39 @@
// Grass
/obj/structure/flora/grass
name = "\proper grass"
desc = "Some grass."
icon = 'icons/obj/flora/snowflora.dmi'
density = FALSE
/obj/structure/flora/grass/brown
icon_state = "snowgrass1bb"
/obj/structure/flora/grass/brown/New()
..()
icon_state = "snowgrass[rand(1, 3)]bb"
/obj/structure/flora/grass/green
icon_state = "snowgrass1gb"
/obj/structure/flora/grass/green/New()
..()
icon_state = "snowgrass[rand(1, 3)]gb"
/obj/structure/flora/grass/both
icon_state = "snowgrassall1"
/obj/structure/flora/grass/both/New()
..()
icon_state = "snowgrassall[rand(1, 3)]"
// Bushes
/obj/structure/flora/bush
name = "bush"
desc = "A bush."
icon = 'icons/obj/flora/snowflora.dmi'
icon_state = "snowbush1"
density = FALSE
/obj/structure/flora/bush/Initialize()
. = ..()
icon_state = "snowbush[rand(1, 6)]"
@@ -0,0 +1,32 @@
/obj/structure/monolith
name = "monolith"
desc = "An obviously artifical structure of unknown origin."
icon = 'icons/obj/monolith.dmi'
icon_state = "jaggy1"
layer = ABOVE_ALL_MOB_LAYER
density = TRUE
anchored = TRUE
var/active = FALSE
var/list/possible_colors = list("#232B2B", COLOR_ASTEROID_ROCK, COLOR_HULL)
/obj/structure/monolith/Initialize()
. = ..()
icon_state = "jaggy[rand(1,4)]"
if(!color)
color = pick(possible_colors)
update_icon()
/obj/structure/monolith/update_icon()
overlays.Cut()
if(active)
var/image/I = image(icon,"[icon_state]decor")
I.appearance_flags = RESET_COLOR
I.color = get_random_colour(0, 150, 255)
I.layer = EFFECTS_ABOVE_LIGHTING_LAYER
add_overlay(I)
set_light(0.3, 0.1, 2, l_color = I.color)
var/turf/simulated/floor/exoplanet/T = get_turf(src)
if(istype(T))
var/image/I = overlay_image(icon, "dugin", T.dirt_color, RESET_COLOR)
add_overlay(I)
@@ -0,0 +1,191 @@
/obj/structure/pit
name = "pit"
desc = "Watch your step, partner."
icon = 'icons/obj/pit.dmi'
icon_state = "pit1"
blend_mode = BLEND_MULTIPLY
density = FALSE
anchored = TRUE
var/open = 1
/obj/structure/pit/attackby(obj/item/W, mob/user)
if(istype(W,/obj/item/shovel))
visible_message("<span class='notice'>\The [user] starts [open ? "filling" : "digging open"] \the [src]</span>")
if(W.use_tool(src, user, 50, volume = 50))
visible_message("<span class='notice'>\The [user] [open ? "fills" : "digs open"] \the [src]!</span>")
if(open)
close(user)
else
open()
else
to_chat(user, "<span class='notice'>You stop shoveling.</span>")
return
if (!open && istype(W,/obj/item/stack/material/wood))
if(locate(/obj/structure/gravemarker) in src.loc)
to_chat(user, "<span class='notice'>There's already a grave marker here.</span>")
else
visible_message("<span class='notice'>\The [user] starts making a grave marker on top of \the [src]</span>")
if( do_after(user, 50) )
visible_message("<span class='notice'>\The [user] finishes the grave marker</span>")
var/obj/item/stack/material/wood/plank = W
plank.use(1)
new/obj/structure/gravemarker(src.loc)
else
to_chat(user, "<span class='notice'>You stop making a grave marker.</span>")
return
..()
/obj/structure/pit/update_icon()
icon_state = "pit[open]"
if(istype(loc,/turf/simulated/floor/exoplanet))
var/turf/simulated/floor/exoplanet/E = loc
if(E.dirt_color)
color = E.dirt_color
/obj/structure/pit/proc/open()
name = "pit"
desc = "Watch your step, partner."
open = 1
for(var/atom/movable/A in src)
A.forceMove(src.loc)
update_icon()
/obj/structure/pit/proc/close(var/user)
name = "mound"
desc = "Some things are better left buried."
open = 0
for(var/atom/movable/A in src.loc)
if(!A.anchored && A != user)
A.forceMove(src)
update_icon()
/obj/structure/pit/return_air()
if(open && loc)
return loc.return_air()
/obj/structure/pit/proc/digout(mob/escapee)
var/breakout_time = 1 //2 minutes by default
if(open)
return
if(escapee.stat || escapee.restrained())
return
escapee.setClickCooldown(100)
to_chat(escapee, "<span class='warning'>You start digging your way out of \the [src] (this will take about [breakout_time] minute\s)</span>")
visible_message("<span class='danger'>Something is scratching its way out of \the [src]!</span>")
for(var/i in 1 to (6*breakout_time * 2)) //minutes * 6 * 5seconds * 2
playsound(src.loc, 'sound/weapons/bite.ogg', 100, 1)
if(!do_after(escapee, 50))
to_chat(escapee, "<span class='warning'>You have stopped digging.</span>")
return
if(open)
return
if(i == 6*breakout_time)
to_chat(escapee, "<span class='warning'>Halfway there...</span>")
to_chat(escapee, "<span class='warning'>You successfuly dig yourself out!</span>")
visible_message("<span class='danger'>\the [escapee] emerges from \the [src]!</span>")
playsound(src.loc, 'sound/effects/squelch1.ogg', 100, 1)
open()
/obj/structure/pit/Crossed(AM as mob|obj)
for(var/obj/item/landmine/I in contents)
I.Crossed(AM, TRUE)
..()
/obj/structure/pit/closed
name = "mound"
desc = "Some things are better left buried."
open = FALSE
/obj/structure/pit/closed/Initialize()
. = ..()
close()
//invisible until unearthed first
/obj/structure/pit/closed/hidden
invisibility = INVISIBILITY_OBSERVER
/obj/structure/pit/closed/hidden/open()
..()
set_invisibility(INVISIBILITY_LEVEL_ONE)
//buried land mines
/obj/structure/pit/landmine
name = "mound"
desc = "Some things are better left buried."
open = FALSE
var/landmine_prob = 25
/obj/structure/pit/landmine/Initialize()
. = ..()
if(prob(landmine_prob))
new /obj/item/landmine(src)
close()
/obj/structure/pit/landmine/hidden
invisibility = INVISIBILITY_OBSERVER
/obj/structure/pit/landmine/hidden/open()
..()
set_invisibility(INVISIBILITY_LEVEL_ONE)
//spoooky
/obj/structure/pit/closed/grave
name = "grave"
icon_state = "pit0"
/obj/structure/pit/closed/grave/Initialize()
var/obj/structure/closet/crate/coffin/C = new(src.loc)
var/obj/effect/decal/remains/human/bones = new(C)
bones.layer = BELOW_MOB_LAYER
var/obj/structure/gravemarker/random/R = new(src.loc)
R.generate()
. = ..()
/obj/structure/gravemarker
name = "grave marker"
desc = "You're not the first."
icon = 'icons/obj/gravestone.dmi'
icon_state = "wood"
pixel_x = 15
pixel_y = 8
anchored = TRUE
var/message = "Unknown."
/obj/structure/gravemarker/cross
icon_state = "cross"
/obj/structure/gravemarker/examine(mob/user)
. = ..()
to_chat(user, "It says: '[message]'")
/obj/structure/gravemarker/random/Initialize()
generate()
. = ..()
/obj/structure/gravemarker/random/proc/generate()
icon_state = pick("wood","cross")
var/nam = random_name(MALE, SPECIES_HUMAN)
message = "Here lies [nam]."
/obj/structure/gravemarker/attackby(obj/item/W, mob/user)
if(istype(W,/obj/item/material/hatchet))
visible_message("<span class = 'warning'>\The [user] starts hacking away at \the [src] with \the [W].</span>")
if(!do_after(user, 30))
visible_message("<span class = 'warning'>\The [user] hacks \the [src] apart.</span>")
new /obj/item/stack/material/wood(src)
qdel(src)
if(istype(W,/obj/item/pen))
var/msg = sanitize(input(user, "What should it say?", "Grave marker", message) as text|null)
if(msg)
message = msg
@@ -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()
@@ -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"
@@ -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
@@ -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)]"
@@ -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"
@@ -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)]"
@@ -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)]"
@@ -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
@@ -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("<span class='notice'>[user] fills \the [RG] from \the [src].</span>","<span class='notice'>You fill \the [RG] from \the [src].</span>")
else
return ..()
+6 -30
View File
@@ -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
@@ -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()
-82
View File
@@ -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)
@@ -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()
@@ -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)
)
)
@@ -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
)
)
@@ -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
)
@@ -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
)
@@ -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
)
@@ -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
)
)
@@ -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
)
)