diff --git a/code/__DEFINES/planes.dm b/code/__DEFINES/planes.dm
new file mode 100644
index 0000000000..31165e0258
--- /dev/null
+++ b/code/__DEFINES/planes.dm
@@ -0,0 +1,18 @@
+//List of all preclaimed planes
+ //Generally 'arbitrary' planes should be given a constant number
+ //Planes that are dependent upon another plane value should be defined with that plane
+ #define PLANE_SPACE_BACKGROUND -10
+ #define PLANE_SPACE_PARALLAX (PLANE_SPACE_BACKGROUND + 1)
+ #define PLANE_SPACE_DUST (PLANE_SPACE_PARALLAX + 1)
+
+ #define PLANE_TURF -6
+ #define PLANE_NOIR_BLOOD -5
+ #define PLANE_OBJ -4
+ #define PLANE_MOB -3
+ #define PLANE_EFFECTS -2
+ #define PLANE_LIGHTING -1
+
+ #define PLANE_BASE 0
+
+ #define PLANE_STATIC 1
+ #define PLANE_HUD 2
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 19ff525dc8..ce5fc3f223 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1437,4 +1437,12 @@ proc/pick_closest_path(value)
var/str = "[val]"
while(length(str) < 5)
str = "0" + str
- . = str
\ No newline at end of file
+ . = str
+
+/proc/trange(var/Dist = 0, var/turf/Center = null)
+ if (isnull(Center))
+ return
+
+ var/turf/x1y1 = locate(((Center.x - Dist) < 1 ? 1 : Center.x - Dist), ((Center.y - Dist) < 1 ? 1 : Center.y - Dist), Center.z)
+ var/turf/x2y2 = locate(((Center.x + Dist) > world.maxx ? world.maxx : Center.x + Dist), ((Center.y + Dist) > world.maxy ? world.maxy : Center.y + Dist), Center.z)
+ return block(x1y1, x2y2)
diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm
index baa881732a..7070009029 100644
--- a/code/_globalvars/misc.dm
+++ b/code/_globalvars/misc.dm
@@ -19,4 +19,9 @@ var/map_ready = 0
Therefore, we'd need to use spawn() inside New() to wait for the surrounding turf contents to be instanced
However, using lots of spawn() has a severe performance impact, and often results in spaghetti-code
map_ready will be set to 1 when world/New() is called (which happens just after the map is instanced)
-*/
\ No newline at end of file
+*/
+
+//SPACE PARALLAX
+var/parallax_initialized = 0
+var/space_color = "#050505"
+var/list/parallax_icon[27]
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 68dc004363..591e47f83d 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -179,6 +179,7 @@
mymob.update_action_buttons(1)
reorganize_alerts()
mymob.reload_fullscreen()
+ update_parallax_existence()
/datum/hud/human/show_hud(version = 0)
@@ -205,4 +206,3 @@
usr << "Switched HUD mode. Press F12 to toggle."
else
usr << "This mob type does not use a HUD."
-
diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm
new file mode 100644
index 0000000000..7f0e283dde
--- /dev/null
+++ b/code/_onclick/hud/parallax.dm
@@ -0,0 +1,254 @@
+/*
+ * This file handles all parallax-related business once the parallax itself is initialized with the rest of the HUD
+ */
+#define PARALLAX_IMAGE_WIDTH 15
+#define PARALLAX_IMAGE_TILES (PARALLAX_IMAGE_WIDTH**2)
+
+var/list/parallax_on_clients = list()
+
+/obj/screen/parallax
+ var/base_offset_x = 0
+ var/base_offset_y = 0
+ mouse_opacity = 0
+ icon = 'icons/turf/space.dmi'
+ icon_state = "blank"
+ name = "space parallax"
+ screen_loc = "CENTER,CENTER"
+ blend_mode = BLEND_ADD
+ layer = AREA_LAYER
+ plane = PLANE_SPACE_PARALLAX
+ var/parallax_speed = 0
+
+/obj/screen/plane_master
+ appearance_flags = PLANE_MASTER
+ screen_loc = "CENTER,CENTER"
+
+/obj/screen/plane_master/parallax_master
+ plane = PLANE_SPACE_PARALLAX
+ blend_mode = BLEND_MULTIPLY
+ color = list(
+ 1,0,0,0,
+ 0,1,0,0,
+ 0,0,1,0,
+ 0,0,0,0,
+ 0,0,0,1)
+
+/obj/screen/plane_master/parallax_spacemaster //Turns space white, causing the parallax to only show in areas with opacity. Somehow
+ plane = PLANE_SPACE_BACKGROUND
+ color = list(
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 1,1,1,1,
+ 0,0,0,0)
+
+/obj/screen/plane_master/parallax_spacemaster/New()
+ ..()
+ overlays += image(icon = 'icons/mob/screen1.dmi', icon_state = "blank")
+
+/obj/screen/plane_master/parallax_dustmaster
+ plane = PLANE_SPACE_DUST
+ color = list(0,0,0,0)
+
+/datum/hud/proc/update_parallax_existence()
+ if(!parallax_initialized)
+ return
+ initialize_parallax()
+ update_parallax()
+ update_parallax_values()
+
+/datum/hud/proc/initialize_parallax()
+ var/client/C = mymob.client
+
+ if(!C.parallax_master)
+ C.parallax_master = PoolOrNew(/obj/screen/plane_master/parallax_master)
+ if(!C.parallax_spacemaster)
+ C.parallax_spacemaster = PoolOrNew(/obj/screen/plane_master/parallax_spacemaster)
+ if(!C.parallax_dustmaster)
+ C.parallax_dustmaster = PoolOrNew(/obj/screen/plane_master/parallax_dustmaster)
+
+ if(!C.parallax.len)
+ for(var/obj/screen/parallax/bgobj in parallax_icon)
+ var/obj/screen/parallax/parallax_layer = PoolOrNew(/obj/screen/parallax)
+ parallax_layer.appearance = bgobj.appearance
+ parallax_layer.base_offset_x = bgobj.base_offset_x
+ parallax_layer.base_offset_y = bgobj.base_offset_y
+ parallax_layer.parallax_speed = bgobj.parallax_speed
+ parallax_layer.screen_loc = bgobj.screen_loc
+ C.parallax += parallax_layer
+ if(bgobj.parallax_speed)
+ C.parallax_movable += parallax_layer
+
+ if(!C.parallax_offset.len)
+ C.parallax_offset["horizontal"] = 0
+ C.parallax_offset["vertical"] = 0
+
+ C.screen |= C.parallax_dustmaster
+
+/datum/hud/proc/update_parallax()
+ var/client/C = mymob.client
+ if(C.prefs.space_parallax)
+ parallax_on_clients |= C
+ for(var/obj/screen/parallax/bgobj in C.parallax)
+ C.screen |= bgobj
+ C.screen |= C.parallax_master
+ C.screen |= C.parallax_spacemaster
+ if(C.prefs.space_dust)
+ C.parallax_dustmaster.color = list(
+ 1,0,0,0,
+ 0,1,0,0,
+ 0,0,1,0,
+ 0,0,0,1)
+ else
+ C.parallax_dustmaster.color = list(0,0,0,0)
+ else
+ for(var/obj/screen/parallax/bgobj in C.parallax)
+ C.screen -= bgobj
+ parallax_on_clients -= C
+ C.screen -= C.parallax_master
+ C.screen -= C.parallax_spacemaster
+ C.parallax_dustmaster.color = list(0,0,0,0)
+
+/datum/hud/proc/update_parallax_values()
+ var/client/C = mymob.client
+ if(!parallax_initialized)
+ return
+
+ if(!(locate(/turf/open/space) in trange(C.view,get_turf(C.eye))))
+ return
+
+ //ACTUALLY MOVING THE PARALLAX
+ var/turf/posobj = get_turf(C.eye)
+
+ if(!C.previous_turf || (C.previous_turf.z != posobj.z))
+ C.previous_turf = posobj
+
+ //Doing it this way prevents parallax layers from "jumping" when you change Z-Levels.
+ var/offsetx = C.parallax_offset["horizontal"] + posobj.x - C.previous_turf.x
+ var/offsety = C.parallax_offset["vertical"] + posobj.y - C.previous_turf.y
+ C.parallax_offset["horizontal"] = offsetx
+ C.parallax_offset["vertical"] = offsety
+
+ C.previous_turf = posobj
+
+ var/maxoffset = 480 //480 = (15 tiles * 32 icon_size * 3 grid size / 2) - (15 tiles * 32 icon size / 2) for centering
+ var/minoffset = -960 //960 = (15 tiles * 32 icon_size * 3 grid size / 2) + (15 tiles * 32 icon size / 2) for centering
+
+ for(var/obj/screen/parallax/bgobj in C.parallax_movable)
+ var/accumulated_offset_x = bgobj.base_offset_x - round(offsetx * bgobj.parallax_speed * C.prefs.parallax_speed)
+ var/accumulated_offset_y = bgobj.base_offset_y - round(offsety * bgobj.parallax_speed * C.prefs.parallax_speed)
+
+ if(accumulated_offset_x > maxoffset)
+ accumulated_offset_x -= 1440 //3x3 grid, 15 tiles * 32 icon_size * 3 grid size
+ if(accumulated_offset_x < minoffset)
+ accumulated_offset_x += 1440
+
+ if(accumulated_offset_y > maxoffset)
+ accumulated_offset_y -= 1440
+ if(accumulated_offset_y < minoffset)
+ accumulated_offset_y += 1440
+
+ bgobj.screen_loc = "CENTER:[accumulated_offset_x],CENTER:[accumulated_offset_y]"
+
+//Parallax generation code below
+
+#define PARALLAX4_ICON_NUMBER 20
+#define PARALLAX3_ICON_NUMBER 14
+#define PARALLAX2_ICON_NUMBER 10
+
+/datum/subsystem/parallax/proc/create_global_parallax_icons()
+ var/list/plane1 = list()
+ var/list/plane2 = list()
+ var/list/plane3 = list()
+ var/list/pixel_x = list()
+ var/list/pixel_y = list()
+ var/index = 1
+ for(var/i = 0 to (PARALLAX_IMAGE_TILES-1))
+ for(var/j = 1 to 9)
+ plane1 += rand(1,26)
+ plane2 += rand(1,26)
+ plane3 += rand(1,26)
+ pixel_x += world.icon_size * (i%PARALLAX_IMAGE_WIDTH)
+ pixel_y += world.icon_size * round(i/PARALLAX_IMAGE_WIDTH)
+
+ for(var/i in 0 to 8)
+ var/obj/screen/parallax/parallax_layer = PoolOrNew(/obj/screen/parallax)
+
+ var/list/L = list()
+ for(var/j in 1 to PARALLAX_IMAGE_TILES)
+ if(plane1[j+i*PARALLAX_IMAGE_TILES] <= PARALLAX4_ICON_NUMBER)
+ var/image/I = image('icons/turf/space_parallax4.dmi',"[plane1[j+i*PARALLAX_IMAGE_TILES]]")
+ I.pixel_x = pixel_x[j]
+ I.pixel_y = pixel_y[j]
+ L += I
+
+ parallax_layer.overlays = L
+ parallax_layer.parallax_speed = 0
+ parallax_layer.calibrate_parallax(i+1)
+ parallax_icon[index] = parallax_layer
+ index++
+
+ for(var/i in 0 to 8)
+ var/obj/screen/parallax/parallax_layer = PoolOrNew(/obj/screen/parallax)
+
+ var/list/L = list()
+ for(var/j in 1 to PARALLAX_IMAGE_TILES)
+ if(plane2[j+i*PARALLAX_IMAGE_TILES] <= PARALLAX3_ICON_NUMBER)
+ var/image/I = image('icons/turf/space_parallax3.dmi',"[plane2[j+i*PARALLAX_IMAGE_TILES]]")
+ I.pixel_x = pixel_x[j]
+ I.pixel_y = pixel_y[j]
+ L += I
+
+ parallax_layer.overlays = L
+ parallax_layer.parallax_speed = 0.5
+ parallax_layer.calibrate_parallax(i+1)
+ parallax_icon[index] = parallax_layer
+ index++
+
+ for(var/i in 0 to 8)
+ var/obj/screen/parallax/parallax_layer = PoolOrNew(/obj/screen/parallax)
+ var/list/L = list()
+ for(var/j in 1 to PARALLAX_IMAGE_TILES)
+ if(plane3[j+i*PARALLAX_IMAGE_TILES] <= PARALLAX2_ICON_NUMBER)
+ var/image/I = image('icons/turf/space_parallax2.dmi',"[plane3[j+i*PARALLAX_IMAGE_TILES]]")
+ I.pixel_x = pixel_x[j]
+ I.pixel_y = pixel_y[j]
+ L += I
+
+ parallax_layer.overlays = L
+ parallax_layer.parallax_speed = 1
+ parallax_layer.calibrate_parallax(i+1)
+ parallax_icon[index] = parallax_layer
+ index++
+
+ parallax_initialized = 1
+
+/obj/screen/parallax/proc/calibrate_parallax(var/i)
+ if(!i) return
+
+ /* Placement of screen objects
+ 1 2 3
+ 4 5 6
+ 7 8 9
+ */
+ base_offset_x = -PARALLAX_IMAGE_WIDTH*world.icon_size/2
+ base_offset_y = -PARALLAX_IMAGE_WIDTH*world.icon_size/2
+
+ switch(i)
+ if(1,4,7)
+ base_offset_x -= world.icon_size*PARALLAX_IMAGE_WIDTH
+ if(3,6,9)
+ base_offset_x += world.icon_size*PARALLAX_IMAGE_WIDTH
+ switch(i)
+ if(1,2,3)
+ base_offset_y += world.icon_size*PARALLAX_IMAGE_WIDTH
+ if(7,8,9)
+ base_offset_y -= world.icon_size*PARALLAX_IMAGE_WIDTH
+
+ screen_loc = "CENTER:[base_offset_x],CENTER:[base_offset_y]"
+
+#undef PARALLAX4_ICON_NUMBER
+#undef PARALLAX3_ICON_NUMBER
+#undef PARALLAX2_ICON_NUMBER
+#undef PARALLAX_IMAGE_WIDTH
+#undef PARALLAX_IMAGE_TILES
diff --git a/code/controllers/subsystem/parallax.dm b/code/controllers/subsystem/parallax.dm
new file mode 100644
index 0000000000..5f8f373212
--- /dev/null
+++ b/code/controllers/subsystem/parallax.dm
@@ -0,0 +1,12 @@
+var/datum/subsystem/parallax/SSparallax
+
+/datum/subsystem/parallax
+ name = "Space Parallax"
+ init_order = 18
+ flags = SS_NO_FIRE
+
+/datum/subsystem/parallax/New()
+ NEW_SS_GLOBAL(SSparallax)
+
+/datum/subsystem/parallax/Initialize()
+ create_global_parallax_icons()
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 4a5dd97ac3..1db488d119 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -69,6 +69,8 @@
last_move = 0
return
+ update_client_hook(loc)
+
if(.)
Moved(oldloc, direct)
@@ -132,6 +134,9 @@
continue
AM.Crossed(src)
Moved(oldloc, 0)
+
+ update_client_hook(destination)
+
return 1
return 0
@@ -152,13 +157,26 @@
else //something went very wrong.
CRASH("Brainmob without container.")
-
/mob/living/silicon/pai/forceMove(atom/destination)
if(card)
card.forceMove(destination)
else //something went very wrong.
CRASH("pAI without card")
+/atom/movable/proc/update_client_hook(atom/destination)
+ if(locate(/mob) in src)
+ for(var/client/C in parallax_on_clients)
+ if((get_turf(C.eye) == destination) && (C.mob.hud_used))
+ C.mob.hud_used.update_parallax_values()
+
+/mob/update_client_hook(atom/destination)
+ if(locate(/mob) in src)
+ for(var/client/C in parallax_on_clients)
+ if((get_turf(C.eye) == destination) && (C.mob.hud_used))
+ C.mob.hud_used.update_parallax_values()
+ else if(client && hud_used)
+ hud_used.update_parallax_values()
+
//Called whenever an object moves and by mobs when they attempt to move themselves through space
//And when an object or action applies a force on src, see newtonian_move() below
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 22f510ca1d..f1d2b9db03 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -5,6 +5,8 @@
desc = "A vast, cold, and lonely place."
intact = 0
+ plane = PLANE_SPACE_BACKGROUND
+
temperature = TCMB
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
heat_capacity = 700000
@@ -21,6 +23,11 @@
/turf/open/space/New()
update_icon()
air = space_gas
+ var/image/I = image('icons/turf/space_parallax1.dmi',"[icon_state]")
+ I.plane = PLANE_SPACE_DUST
+ I.alpha = 80
+ I.blend_mode = BLEND_ADD
+ overlays += I
/turf/open/space/Destroy(force)
if(force)
diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm
index 13e75be663..85d3fc6357 100644
--- a/code/game/turfs/space/transit.dm
+++ b/code/game/turfs/space/transit.dm
@@ -2,6 +2,7 @@
icon_state = "black"
dir = SOUTH
baseturf = /turf/open/space/transit
+ plane = PLANE_TURF
/turf/open/space/transit/horizontal
dir = WEST
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index 5aff1278e1..f5283695ff 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -51,4 +51,15 @@
var/datum/tooltip/tooltips
//Used for var edit flagging, also defined in datums (clients are not a child of datums for some reason)
- var/var_edited = 0
\ No newline at end of file
+ var/var_edited = 0
+
+ ////////////
+ //PARALLAX//
+ ////////////
+ var/list/parallax = list()
+ var/list/parallax_movable = list()
+ var/list/parallax_offset = list()
+ var/turf/previous_turf = null
+ var/obj/screen/plane_master/parallax_master/parallax_master = null
+ var/obj/screen/plane_master/parallax_dustmaster/parallax_dustmaster = null
+ var/obj/screen/plane_master/parallax_spacemaster/parallax_spacemaster = null
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 7a22e62d31..31b761de66 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -117,6 +117,11 @@ var/list/preferences_datums = list()
var/list/ignoring = list()
+ //Parallax prefs
+ var/space_parallax = 1
+ var/space_dust = 1
+ var/parallax_speed = 2
+
/datum/preferences/New(client/C)
custom_names["ai"] = pick(ai_names)
custom_names["cyborg"] = pick(ai_names)
@@ -448,6 +453,10 @@ var/list/preferences_datums = list()
dat += "Ghost pda: [(chat_toggles & CHAT_GHOSTPDA) ? "All Messages" : "Nearest Creatures"]
"
dat += "Pull requests: [(chat_toggles & CHAT_PULLR) ? "Yes" : "No"]
"
dat += "Midround Antagonist: [(toggles & MIDROUND_ANTAG) ? "Yes" : "No"]
"
+ dat += "Space Parallax: [space_parallax ? "Enabled" : "Disabled"]
"
+ if(space_parallax)
+ dat += "Parallax Speed: [parallax_speed]
"
+ dat += "Space Dust: [space_dust ? "Yes" : "No"]
"
if(config.allow_Metadata)
dat += "OOC Notes: Edit
"
@@ -1275,6 +1284,15 @@ var/list/preferences_datums = list()
else
be_special += be_special_type
+ if("parallax")
+ space_parallax = !space_parallax
+
+ if("dust")
+ space_dust = !space_dust
+
+ if("p_speed")
+ parallax_speed = min(max(input(user, "Enter a number between 0 and 5 included (default=2)","Parallax Speed Preferences",parallax_speed),0),5)
+
if("name")
be_random_name = !be_random_name
@@ -1399,4 +1417,4 @@ var/list/preferences_datums = list()
if(icon_updates)
character.update_body()
character.update_hair()
- character.update_body_parts()
\ No newline at end of file
+ character.update_body_parts()
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index d79b57ff93..7288c42f23 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -237,6 +237,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["hotkeys"] >> hotkeys
S["tgui_fancy"] >> tgui_fancy
S["tgui_lock"] >> tgui_lock
+ S["space_parallax"] >> space_parallax
+ S["space_dust"] >> space_dust
+ S["parallax_speed"] >> parallax_speed
if(islist(S["be_special"]))
S["be_special"] >> be_special
@@ -270,6 +273,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
tgui_lock = sanitize_integer(tgui_lock, 0, 1, initial(tgui_lock))
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
toggles = sanitize_integer(toggles, 0, 65535, initial(toggles))
+ space_parallax = sanitize_integer(space_parallax, 0, 1, initial(space_parallax))
+ space_dust = sanitize_integer(space_dust, 0, 1, initial(space_dust))
+ parallax_speed = sanitize_integer(parallax_speed, 0, 5, initial(parallax_speed))
ghost_form = sanitize_inlist(ghost_form, ghost_forms, initial(ghost_form))
ghost_orbit = sanitize_inlist(ghost_orbit, ghost_orbits, initial(ghost_orbit))
ghost_accs = sanitize_inlist(ghost_accs, ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION)
@@ -306,6 +312,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ignoring"] << ignoring
S["ghost_hud"] << ghost_hud
S["inquisitive_ghost"] << inquisitive_ghost
+ S["space_parallax"] << space_parallax
+ S["space_dust"] << space_dust
+ S["parallax_speed"] << parallax_speed
return 1
@@ -556,4 +565,4 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
/client/verb/savefile_import(path as text)
var/savefile/S = new /savefile(path)
S.ImportText("/",file("[path].txt"))
-*/
\ No newline at end of file
+*/
diff --git a/icons/mob/screen1.dmi b/icons/mob/screen1.dmi
new file mode 100644
index 0000000000..51e5df832b
Binary files /dev/null and b/icons/mob/screen1.dmi differ
diff --git a/icons/turf/screen1_parallax.dmi b/icons/turf/screen1_parallax.dmi
new file mode 100644
index 0000000000..cd0f232bbc
Binary files /dev/null and b/icons/turf/screen1_parallax.dmi differ
diff --git a/icons/turf/shuttle.dmi b/icons/turf/shuttle.dmi
index 1a7fa3c9bd..a49c19226f 100644
Binary files a/icons/turf/shuttle.dmi and b/icons/turf/shuttle.dmi differ
diff --git a/icons/turf/space.dmi b/icons/turf/space.dmi
index d32279e704..dc6a28d285 100644
Binary files a/icons/turf/space.dmi and b/icons/turf/space.dmi differ
diff --git a/icons/turf/space_parallax1.dmi b/icons/turf/space_parallax1.dmi
new file mode 100644
index 0000000000..a538bf0f0d
Binary files /dev/null and b/icons/turf/space_parallax1.dmi differ
diff --git a/icons/turf/space_parallax2.dmi b/icons/turf/space_parallax2.dmi
new file mode 100644
index 0000000000..e93cc831d4
Binary files /dev/null and b/icons/turf/space_parallax2.dmi differ
diff --git a/icons/turf/space_parallax3.dmi b/icons/turf/space_parallax3.dmi
new file mode 100644
index 0000000000..2261ab17f7
Binary files /dev/null and b/icons/turf/space_parallax3.dmi differ
diff --git a/icons/turf/space_parallax4.dmi b/icons/turf/space_parallax4.dmi
new file mode 100644
index 0000000000..560bacd009
Binary files /dev/null and b/icons/turf/space_parallax4.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 9f0a602fe0..8b2b7e3725 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -40,6 +40,7 @@
#include "code\__DEFINES\math.dm"
#include "code\__DEFINES\misc.dm"
#include "code\__DEFINES\pipe_construction.dm"
+#include "code\__DEFINES\planes.dm"
#include "code\__DEFINES\preferences.dm"
#include "code\__DEFINES\qdel.dm"
#include "code\__DEFINES\radio.dm"
@@ -125,6 +126,7 @@
#include "code\_onclick\hud\monkey.dm"
#include "code\_onclick\hud\movable_screen_objects.dm"
#include "code\_onclick\hud\other_mobs.dm"
+#include "code\_onclick\hud\parallax.dm"
#include "code\_onclick\hud\revenanthud.dm"
#include "code\_onclick\hud\robot.dm"
#include "code\_onclick\hud\screen_objects.dm"
@@ -168,6 +170,7 @@
#include "code\controllers\subsystem\npcpool.dm"
#include "code\controllers\subsystem\objects.dm"
#include "code\controllers\subsystem\pai.dm"
+#include "code\controllers\subsystem\parallax.dm"
#include "code\controllers\subsystem\radio.dm"
#include "code\controllers\subsystem\server_maintenance.dm"
#include "code\controllers\subsystem\shuttles.dm"