diff --git a/code/_macros.dm b/code/_macros.dm
index 1038b6a2e4..463a7da26d 100644
--- a/code/_macros.dm
+++ b/code/_macros.dm
@@ -42,6 +42,8 @@
#define isxeno(A) istype(A, /mob/living/simple_animal/xeno)
+#define isopenspace(A) istype(A, /turf/simulated/open)
+
#define isweakref(A) istype(A, /weakref)
#define RANDOM_BLOOD_TYPE pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index b511c9befd..fe9f99b032 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -115,12 +115,7 @@
else if(isturf(hit_atom))
src.throwing = 0
var/turf/T = hit_atom
- if(T.density)
- spawn(2)
- step(src, turn(src.last_move, 180))
- if(istype(src,/mob/living))
- var/mob/living/M = src
- M.turf_collision(T, speed)
+ T.hitby(src,speed)
//decided whether a movable atom being thrown can pass through the turf it is in.
/atom/movable/proc/hit_check(var/speed)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index c13b4606d3..028223ef26 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -243,3 +243,11 @@ var/const/enterloopsanity = 100
/turf/proc/update_blood_overlays()
return
+// Called when turf is hit by a thrown object
+/turf/hitby(atom/movable/AM as mob|obj, var/speed)
+ if(src.density)
+ spawn(2)
+ step(AM, turn(AM.last_move, 180))
+ if(isliving(AM))
+ var/mob/living/M = AM
+ M.turf_collision(src, speed)
diff --git a/code/modules/multiz/basic.dm b/code/modules/multiz/basic.dm
index e76c6516aa..24d24b1049 100644
--- a/code/modules/multiz/basic.dm
+++ b/code/modules/multiz/basic.dm
@@ -11,25 +11,35 @@ var/z_levels = 0 // Each bit represents a connection between adjacent levels. S
qdel(src)
// The storage of connections between adjacent levels means some bitwise magic is needed.
-proc/HasAbove(var/z)
+/proc/HasAbove(var/z)
if(z >= world.maxz || z > 16 || z < 1)
return 0
return z_levels & (1 << (z - 1))
-proc/HasBelow(var/z)
+/proc/HasBelow(var/z)
if(z > world.maxz || z > 17 || z < 2)
return 0
return z_levels & (1 << (z - 2))
// Thankfully, no bitwise magic is needed here.
-proc/GetAbove(var/atom/atom)
+/proc/GetAbove(var/atom/atom)
var/turf/turf = get_turf(atom)
if(!turf)
return null
return HasAbove(turf.z) ? get_step(turf, UP) : null
-proc/GetBelow(var/atom/atom)
+/proc/GetBelow(var/atom/atom)
var/turf/turf = get_turf(atom)
if(!turf)
return null
return HasBelow(turf.z) ? get_step(turf, DOWN) : null
+
+/proc/GetConnectedZlevels(z)
+ . = list(z)
+ for(var/level = z, HasBelow(level), level--)
+ . |= level-1
+ for(var/level = z, HasAbove(level), level++)
+ . |= level+1
+
+proc/AreConnectedZLevels(var/zA, var/zB)
+ return zA == zB || (zB in GetConnectedZlevels(zA))
diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm
index 586b624260..122e1aa4cd 100644
--- a/code/modules/multiz/movement.dm
+++ b/code/modules/multiz/movement.dm
@@ -3,34 +3,38 @@
set category = "IC"
if(zMove(UP))
- to_chat(usr, "You move upwards.")
+ to_chat(src, "You move upwards.")
/mob/verb/down()
set name = "Move Down"
set category = "IC"
if(zMove(DOWN))
- to_chat(usr, "You move down.")
+ to_chat(src, "You move down.")
/mob/proc/zMove(direction)
if(eyeobj)
return eyeobj.zMove(direction)
if(!can_ztravel())
- to_chat(usr, "You lack means of travel in that direction.")
+ to_chat(src, "You lack means of travel in that direction.")
return
+ var/turf/start = loc
+ if(!istype(start))
+ to_chat(src, "You are unable to move from here.")
+ return 0
+
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
-
if(!destination)
- to_chat(usr, "There is nothing of interest in this direction.")
+ to_chat(src, "There is nothing of interest in this direction.")
+ return 0
+
+ if(!start.CanZPass(src, direction))
+ to_chat(src, "\The [start] is in the way.")
return 0
- var/turf/start = get_turf(src)
- if(!start.CanZPass(src, direction))
- to_chat(usr, "\The [start] is in the way.")
- return 0
if(!destination.CanZPass(src, direction))
- to_chat(usr, "\The [destination] blocks your way.")
+ to_chat(src, "\The [destination] blocks your way.")
return 0
var/area/area = get_area(src)
@@ -46,12 +50,12 @@
to_chat(src, "You gave up on pulling yourself up.")
return 0
else
- to_chat(usr, "Gravity stops you from moving upward.")
+ to_chat(src, "Gravity stops you from moving upward.")
return 0
for(var/atom/A in destination)
if(!A.CanPass(src, start, 1.5, 0))
- to_chat(usr, "\The [A] blocks you.")
+ to_chat(src, "\The [A] blocks you.")
return 0
Move(destination)
return 1
@@ -61,14 +65,14 @@
if(destination)
forceMove(destination)
else
- to_chat(usr, "There is nothing of interest in this direction.")
+ to_chat(src, "There is nothing of interest in this direction.")
/mob/observer/eye/zMove(direction)
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
if(destination)
setLoc(destination)
else
- to_chat(usr, "There is nothing of interest in this direction.")
+ to_chat(src, "There is nothing of interest in this direction.")
/mob/proc/can_ztravel()
return 0
diff --git a/code/modules/multiz/pipes.dm b/code/modules/multiz/pipes.dm
index 1cb5b9b4da..6b6b24c470 100644
--- a/code/modules/multiz/pipes.dm
+++ b/code/modules/multiz/pipes.dm
@@ -13,6 +13,9 @@ obj/machinery/atmospherics/pipe/zpipe
dir = SOUTH
initialize_directions = SOUTH
+ // node1 is the connection on the same Z
+ // node2 is the connection on the other Z
+
var/minimum_temperature_difference = 300
var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
diff --git a/code/modules/multiz/structures.dm b/code/modules/multiz/structures.dm
index 5727808276..18bb91a9e4 100644
--- a/code/modules/multiz/structures.dm
+++ b/code/modules/multiz/structures.dm
@@ -122,10 +122,6 @@
allowed_directions = UP|DOWN
icon_state = "ladder11"
-
-
-
-
/obj/structure/stairs
name = "Stairs"
desc = "Stairs leading to another deck. Not too useful if the gravity goes out."
diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm
index 8389df7112..b6845d076f 100644
--- a/code/modules/multiz/turf.dm
+++ b/code/modules/multiz/turf.dm
@@ -36,6 +36,11 @@
..()
mover.fall()
+// Called when thrown object lands on this turf.
+/turf/simulated/open/hitby(var/atom/movable/AM, var/speed)
+ . = ..()
+ AM.fall()
+
/turf/simulated/open/proc/update()
below = GetBelow(src)
turf_changed_event.register(below, src, /turf/simulated/open/update_icon)
@@ -82,7 +87,7 @@
return
var/obj/item/stack/rods/R = C
if (R.use(1))
- user << "Constructing support lattice ..."
+ to_chat(user, "Constructing support lattice ...")
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
ReplaceWithLattice()
return
@@ -99,7 +104,7 @@
ChangeTurf(/turf/simulated/floor/airless)
return
else
- user << "The plating is going to need some support."
+ to_chat(user, "The plating is going to need some support.")
//To lay cable.
if(istype(C, /obj/item/stack/cable_coil))
diff --git a/code/modules/turbolift/turbolift_map.dm b/code/modules/turbolift/turbolift_map.dm
index 2e2498f88d..8930bf34d6 100644
--- a/code/modules/turbolift/turbolift_map.dm
+++ b/code/modules/turbolift/turbolift_map.dm
@@ -221,7 +221,7 @@
var/turf/T = locate(int_panel_x, int_panel_y, uz)
lift.control_panel_interior = new(T, lift)
lift.control_panel_interior.set_dir(udir)
- lift.current_floor = lift.floors[uz]
+ lift.current_floor = lift.floors[1]
lift.open_doors()