diff --git a/baystation12.dme b/baystation12.dme
index b1f4bfbe2d6..0a7b3a47959 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -1277,6 +1277,11 @@
#include "code\modules\virus2\helpers.dm"
#include "code\modules\virus2\isolator.dm"
#include "code\modules\virus2\items_devices.dm"
+#include "code\TriDimension\controler.dm"
+#include "code\TriDimension\Movement.dm"
+#include "code\TriDimension\Pipes.dm"
+#include "code\TriDimension\Structures.dm"
+#include "code\TriDimension\Turfs.dm"
#include "code\WorkInProgress\autopsy.dm"
#include "code\WorkInProgress\buildmode.dm"
#include "code\WorkInProgress\explosion_particles.dm"
diff --git a/code/TriDimension/Movement.dm b/code/TriDimension/Movement.dm
index dfb529df5b1..c8cc6cba1ce 100644
--- a/code/TriDimension/Movement.dm
+++ b/code/TriDimension/Movement.dm
@@ -1,49 +1,52 @@
-var/maxZ = 6
-var/minZ = 2
-
-// Maybe it's best to have this hardcoded for whatever we'd add to the map, in order to avoid exploits
-// (such as mining base => admin station)
-// Note that this assumes the ship's top is at z=1 and bottom at z=4
-/obj/item/weapon/tank/jetpack/proc/move_z(cardinal, mob/user as mob)
- if (user.z > 1)
- user << "\red There is nothing of interest in that direction."
- return
- if(allow_thrust(0.01, user))
- switch(cardinal)
- if (UP) // Going up!
- if(user.z > maxZ) // If we aren't at the very top of the ship
- var/turf/T = locate(user.x, user.y, user.z - 1)
- // You can only jetpack up if there's space above, and you're sitting on either hull (on the exterior), or space
- //if(T && istype(T, /turf/space) && (istype(user.loc, /turf/space) || istype(user.loc, /turf/space/*/hull*/)))
- //check through turf contents to make sure there's nothing blocking the way
- if(T && istype(T, /turf/space))
- var/blocked = 0
- for(var/atom/A in T.contents)
- if(T.density)
- blocked = 1
- user << "\red You bump into [T.name]."
- break
- if(!blocked)
- user.Move(T)
- else
- user << "\red You bump into the ship's plating."
+/obj/item/weapon/tank/jetpack/verb/moveup()
+ set name = "Move Upwards"
+ set category = "Object"
+ if(allow_thrust(0.01, usr))
+ var/turf/controlerlocation = locate(1, 1, usr.z)
+ var/legal = 0
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ legal = controler.up
+ if (controler.up)
+ var/turf/T = locate(usr.x, usr.y, controler.up_target)
+ if(T && (istype(T, /turf/space) || istype(T, /turf/simulated/floor/open)))
+ var/blocked = 0
+ for(var/atom/A in T.contents)
+ if(A.density)
+ blocked = 1
+ usr << "\red You bump into [A.name]."
+ break
+ if(!blocked)
+ usr.Move(T)
+ usr << "You move upwards."
else
- user << "\red The ship's gravity well keeps you in orbit!" // Assuming the ship starts on z level 1, you don't want to go past it
+ usr << "\red There is something in your way."
+ if (legal == 0)
+ usr << "There is nothing of interest in this direction."
+ return 1
- if (DOWN) // Going down!
- if (user.z < 1) // If we aren't at the very bottom of the ship, or out in space
- var/turf/T = locate(user.x, user.y, user.z + 1)
- // You can only jetpack down if you're sitting on space and there's space down below, or hull
- if(T && (istype(T, /turf/space) || istype(T, /turf/space/*/hull*/)) && istype(user.loc, /turf/space))
- var/blocked = 0
- for(var/atom/A in T.contents)
- if(T.density)
- blocked = 1
- user << "\red You bump into [T.name]."
- break
- if(!blocked)
- user.Move(T)
- else
- user << "\red You bump into the ship's plating."
+/obj/item/weapon/tank/jetpack/verb/movedown()
+ set name = "Move Downwards"
+ set category = "Object"
+ if(allow_thrust(0.01, usr))
+ var/turf/controlerlocation = locate(1, 1, usr.z)
+ var/legal = 0
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ legal = controler.down
+ if (controler.down == 1)
+ var/turf/T = locate(usr.x, usr.y, controler.down_target)
+ var/turf/S = locate(usr.x, usr.y, usr.z)
+ if(T && (istype(S, /turf/space) || istype(S, /turf/simulated/floor/open)))
+ var/blocked = 0
+ for(var/atom/A in T.contents)
+ if(A.density)
+ blocked = 1
+ usr << "\red You bump into [A.name]."
+ break
+ if(!blocked)
+ usr.Move(T)
+ usr << "You move downwards."
else
- user << "\red The ship's gravity well keeps you in orbit!"
\ No newline at end of file
+ usr << "\red You cant move through the floor."
+ if (legal == 0)
+ usr << "There is nothing of interest in this direction."
+ return 1
diff --git a/code/TriDimension/Pipes.dm b/code/TriDimension/Pipes.dm
index e69de29bb2d..779e2e49088 100644
--- a/code/TriDimension/Pipes.dm
+++ b/code/TriDimension/Pipes.dm
@@ -0,0 +1,191 @@
+////////////////////////////
+// parent class for pipes //
+////////////////////////////
+obj/machinery/atmospherics/pipe/zpipe
+ icon = 'code/TriDimension/multiz_pipe.dmi'
+ icon_state = "up"
+
+ name = "upwards pipe"
+ desc = "A pipe segment to connect upwards."
+
+ volume = 70
+
+ dir = SOUTH
+ initialize_directions = SOUTH
+
+ var/obj/machinery/atmospherics/node1 //connection on the same Z
+ var/obj/machinery/atmospherics/node2 //connection on the other Z
+
+ var/minimum_temperature_difference = 300
+ var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
+
+ var/maximum_pressure = 70*ONE_ATMOSPHERE
+ var/fatigue_pressure = 55*ONE_ATMOSPHERE
+ alert_pressure = 55*ONE_ATMOSPHERE
+
+
+ level = 1
+
+obj/machinery/atmospherics/pipe/zpipe/New()
+ ..()
+ switch(dir)
+ if(SOUTH)
+ initialize_directions = SOUTH
+ if(NORTH)
+ initialize_directions = NORTH
+ if(WEST)
+ initialize_directions = WEST
+ if(EAST)
+ initialize_directions = EAST
+ if(NORTHEAST)
+ initialize_directions = NORTH
+ if(NORTHWEST)
+ initialize_directions = WEST
+ if(SOUTHEAST)
+ initialize_directions = EAST
+ if(SOUTHWEST)
+ initialize_directions = SOUTH
+ initialize()
+
+
+obj/machinery/atmospherics/pipe/zpipe/hide(var/i)
+ if(level == 1 && istype(loc, /turf/simulated))
+ invisibility = i ? 101 : 0
+ update_icon()
+
+obj/machinery/atmospherics/pipe/up/process()
+ if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle
+ ..()
+ else
+ . = PROCESS_KILL
+
+obj/machinery/atmospherics/pipe/zpipe/check_pressure(pressure)
+ var/datum/gas_mixture/environment = loc.return_air()
+
+ var/pressure_difference = pressure - environment.return_pressure()
+
+ if(pressure_difference > maximum_pressure)
+ burst()
+
+ else if(pressure_difference > fatigue_pressure)
+ //TODO: leak to turf, doing pfshhhhh
+ if(prob(5))
+ burst()
+
+ else return 1
+
+obj/machinery/atmospherics/pipe/zpipe/proc/burst()
+ src.visible_message("\red \bold [src] bursts!");
+ playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
+ var/datum/effect/effect/system/smoke_spread/smoke = new
+ smoke.set_up(1,0, src.loc, 0)
+ smoke.start()
+ del(src)
+
+obj/machinery/atmospherics/pipe/zpipe/proc/normalize_dir()
+ if(dir==3)
+ dir = 1
+ else if(dir==12)
+ dir = 4
+
+obj/machinery/atmospherics/pipe/zpipe/Del()
+ if(node1)
+ node1.disconnect(src)
+ if(node2)
+ node2.disconnect(src)
+ ..()
+
+obj/machinery/atmospherics/pipe/zpipe/pipeline_expansion()
+ return list(node1, node2)
+
+obj/machinery/atmospherics/pipe/zpipe/update_icon()
+ return
+
+obj/machinery/atmospherics/pipe/zpipe/disconnect(obj/machinery/atmospherics/reference)
+ if(reference == node1)
+ if(istype(node1, /obj/machinery/atmospherics/pipe))
+ del(parent)
+ node1 = null
+
+ if(reference == node2)
+ if(istype(node2, /obj/machinery/atmospherics/pipe))
+ del(parent)
+ node2 = null
+
+ return null
+/////////////////////////
+// the elusive up pipe //
+/////////////////////////
+obj/machinery/atmospherics/pipe/zpipe/up
+ icon = 'code/TriDimension/multiz_pipe.dmi'
+ icon_state = "up"
+
+ name = "upwards pipe"
+ desc = "A pipe segment to connect upwards."
+
+obj/machinery/atmospherics/pipe/zpipe/up/initialize()
+ normalize_dir()
+ var/node1_dir
+
+ for(var/direction in cardinal)
+ if(direction&initialize_directions)
+ if (!node1_dir)
+ node1_dir = direction
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
+ if(target.initialize_directions & get_dir(target,src))
+ node1 = target
+ break
+
+ var/turf/controlerlocation = locate(1, 1, src.z)
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ if(controler.up)
+ var/turf/above = locate(src.x, src.y, controler.up_target)
+ if(above)
+ for(var/obj/machinery/atmospherics/target in above)
+ if(target.initialize_directions && istype(target, /obj/machinery/atmospherics/pipe/zpipe/down))
+ node2 = target
+ break
+
+
+ var/turf/T = src.loc // hide if turf is not intact
+ hide(T.intact)
+
+///////////////////////
+// and the down pipe //
+///////////////////////
+
+obj/machinery/atmospherics/pipe/zpipe/down
+ icon = 'code/TriDimension/multiz_pipe.dmi'
+ icon_state = "down"
+
+ name = "downwards pipe"
+ desc = "A pipe segment to connect downwards."
+
+obj/machinery/atmospherics/pipe/zpipe/down/initialize()
+ normalize_dir()
+ var/node1_dir
+
+ for(var/direction in cardinal)
+ if(direction&initialize_directions)
+ if (!node1_dir)
+ node1_dir = direction
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
+ if(target.initialize_directions & get_dir(target,src))
+ node1 = target
+ break
+
+ var/turf/controlerlocation = locate(1, 1, src.z)
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ if(controler.down)
+ var/turf/below = locate(src.x, src.y, controler.down_target)
+ if(below)
+ for(var/obj/machinery/atmospherics/target in below)
+ if(target.initialize_directions && istype(target, /obj/machinery/atmospherics/pipe/zpipe/up))
+ node2 = target
+ break
+
+
+ var/turf/T = src.loc // hide if turf is not intact
+ hide(T.intact)
\ No newline at end of file
diff --git a/code/TriDimension/Structures.dm b/code/TriDimension/Structures.dm
index 85e499f7ad4..4da4de449ee 100644
--- a/code/TriDimension/Structures.dm
+++ b/code/TriDimension/Structures.dm
@@ -7,7 +7,6 @@
density = 0
opacity = 0
anchored = 1
- var/obj/multiz/target
CanPass(obj/mover, turf/source, height, airflow)
return airflow || !density
@@ -17,62 +16,137 @@
name = "ladder"
desc = "A Ladder. You climb up and down it."
- var/top_icon_state = "ladderdown"
- var/bottom_icon_state = "ladderup"
+ var/d_state = 1
+ var/obj/multiz/target
New()
. = ..()
- spawn(1) //Allow map to load
- if(z in levels_3d)
- if(!target)
- var/list/adjacent_to_me = global_adjacent_z_levels["[z]"]
- if("up" in adjacent_to_me)
- target = locate() in locate(x,y,adjacent_to_me["up"])
- if(istype(target))
- icon_state = bottom_icon_state
- else if("down" in adjacent_to_me)
- target = locate() in locate(x,y,adjacent_to_me["down"])
- if(istype(target))
- icon_state = top_icon_state
- else
- del src
- else
- del src
- else if("down" in adjacent_to_me)
- target = locate() in locate(x,y,adjacent_to_me["down"])
- if(istype(target))
- icon_state = bottom_icon_state
- else
- del src
- else
- del src
- if(target)
- target.icon_state = ( icon_state == top_icon_state ? bottom_icon_state : top_icon_state)
- target.target = src
- else
- del src
+ connect()
+
+ proc/connect()
+ if(icon_state == "ladderdown") // the upper will connect to the lower
+ d_state = 1
+ var/turf/controlerlocation = locate(1, 1, z)
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ if(controler.down)
+ var/turf/below = locate(src.x, src.y, controler.down_target)
+ for(var/obj/multiz/ladder/L in below)
+ target = L
+ L.target = src
+ d_state = 0
+ break
+ return
+
+/* ex_act(severity)
+ switch(severity)
+ if(1.0)
+ if(icon_state == "ladderup" && prob(10))
+ Del()
+ if(2.0)
+ if(prob(50))
+ Del()
+ if(3.0)
+ Del()
+ return*/
Del()
spawn(1)
- if(target)
+ if(target && icon_state == "ladderdown")
del target
return ..()
attack_paw(var/mob/M)
return attack_hand(M)
- attackby(var/W, var/mob/M)
- return attack_hand(M)
+ attackby(obj/item/C as obj, mob/user as mob)
+ (..)
+// construction commented out for balance concerns
+/* if (!target && istype(C, /obj/item/stack/rods))
+ var/turf/controlerlocation = locate(1, 1, z)
+ var/found = 0
+ var/obj/item/stack/rods/S = C
+ if(S.amount < 2)
+ user << "You dont have enough rods to finish the ladder."
+ return
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ if(controler.down)
+ found = 1
+ var/turf/below = locate(src.x, src.y, controler.down_target)
+ var/blocked = 0
+ for(var/atom/A in below.contents)
+ if(A.density)
+ blocked = 1
+ break
+ if(!blocked && !istype(below, /turf/simulated/wall))
+ var/obj/multiz/ladder/X = new /obj/multiz/ladder(below)
+ S.amount = S.amount - 2
+ if(S.amount == 0) S.Del()
+ X.icon_state = "ladderup"
+ connect()
+ user << "You finish the ladder."
+ else
+ user << "The area below is blocked."
+ if(!found)
+ user << "You cant build a ladder down there."
+ return
+
+ else if (icon_state == "ladderdown" && d_state == 0 && istype(C, /obj/item/weapon/wrench))
+ user << "You start loosening the anchoring bolts which secure the ladder to the frame."
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
+
+ sleep(30)
+ if(!user || !C) return
+
+ src.d_state = 1
+ if(target)
+ var/obj/item/stack/rods/R = new /obj/item/stack/rods(target.loc)
+ R.amount = 2
+ target.Del()
+
+ user << "You remove the bolts anchoring the ladder."
+ return
+
+ else if (icon_state == "ladderdown" && d_state == 1 && istype(C, /obj/item/weapon/weldingtool) )
+ var/obj/item/weapon/weldingtool/WT = C
+ if( WT.remove_fuel(0,user) )
+
+ user << "You begin to remove the ladder."
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+
+ sleep(60)
+ if(!user || !WT || !WT.isOn()) return
+
+ var/obj/item/stack/sheet/metal/S = new /obj/item/stack/sheet/metal( src )
+ S.amount = 2
+ user << "You remove the ladder and close the hole."
+ Del()
+ else
+ user << "You need more welding fuel to complete this task."
+ return
+
+ else
+ src.attack_hand(user)
+ return*/
+ src.attack_hand(user)
+ return
attack_hand(var/mob/M)
if(!target || !istype(target.loc, /turf))
- del src
- var/list/adjacent_to_me = global_adjacent_z_levels["[z]"]
- M.visible_message("\blue \The [M] climbs [target.z == adjacent_to_me["up"] ? "up" : "down"] \the [src]!", "You climb [target.z == adjacent_to_me["up"] ? "up" : "down"] \the [src]!", "You hear some grunting, and clanging of a metal ladder being used.")
- M.Move(target.loc)
+ M << "The ladder is incomplete and cant be climbed."
+ else
+ var/turf/T = target.loc
+ var/blocked = 0
+ for(var/atom/A in T.contents)
+ if(A.density)
+ blocked = 1
+ break
+ if(blocked || istype(T, /turf/simulated/wall))
+ M << "Something is blocking the ladder."
+ else
+ M.visible_message("\blue \The [M] climbs [src.icon_state == "ladderup" ? "up" : "down"] \the [src]!", "You climb [src.icon_state == "ladderup" ? "up" : "down"] \the [src]!", "You hear some grunting, and clanging of a metal ladder being used.")
+ M.Move(target.loc)
-
- hatch
+/* hatch
icon_state = "hatchdown"
name = "hatch"
desc = "A hatch. You climb down it, and it will automatically seal against pressure loss behind you."
@@ -125,81 +199,48 @@
spawn(7)
top_hatch.icon_state = top_icon_state
bottom_hatch.overlays -= red_overlay
- active = 0
+ active = 0*/
/obj/multiz/stairs
name = "Stairs"
desc = "Stairs. You walk up and down them."
- icon_state = "ramptop"
- var/top_icon_state = "ramptop"
- var/bottom_icon_state = "rampbottom"
+ icon_state = "rampbottom"
+ var/obj/multiz/stairs/connected
+ var/turf/target
- active
- density = 1
+ New()
+ ..()
+ var/turf/cl= locate(1, 1, src.z)
+ for(var/obj/effect/landmark/zcontroler/c in cl)
+ if(c.up)
+ var/turf/O = locate(src.x, src.y, c.up_target)
+ if(istype(O, /turf/space))
+ O.ChangeTurf(/turf/simulated/floor/open)
-
- New()
- . = ..()
- spawn(1)
- if(z in levels_3d)
- if(!target)
- var/list/adjacent_to_me = global_adjacent_z_levels["[z]"]
- if("up" in adjacent_to_me)
- target = locate() in locate(x,y,adjacent_to_me["up"])
- if(istype(target))
- icon_state = bottom_icon_state
- else if("down" in adjacent_to_me)
- target = locate() in locate(x,y,adjacent_to_me["down"])
- if(istype(target))
- icon_state = top_icon_state
- else
- del src
- else
- del src
- else if("down" in adjacent_to_me)
- target = locate() in locate(x,y,adjacent_to_me["down"])
- if(istype(target))
- icon_state = bottom_icon_state
- else
- del src
- else
- del src
- if(target)
- target.icon_state = ( icon_state == top_icon_state ? bottom_icon_state : top_icon_state)
- target.target = src
- var/obj/multiz/stairs/lead_in = locate() in get_step(src, reverse_direction(dir))
- if(lead_in)
- lead_in.icon_state = ( icon_state == top_icon_state ? bottom_icon_state : top_icon_state)
- else
- del src
-
-
- Del()
- spawn(1)
+ spawn(1)
+ for(var/dir in cardinal)
+ var/turf/T = get_step(src.loc,dir)
+ for(var/obj/multiz/stairs/S in T)
+ if(S && S.icon_state == "rampbottom" && !S.connected)
+ S.dir = dir
+ src.dir = dir
+ S.connected = src
+ src.connected = S
+ src.icon_state = "ramptop"
+ src.density = 1
+ var/turf/controlerlocation = locate(1, 1, src.z)
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ if(controler.up)
+ var/turf/above = locate(src.x, src.y, controler.up_target)
+ if(istype(above,/turf/space) || istype(above,/turf/simulated/floor/open))
+ src.target = above
+ break
if(target)
- del target
- return ..()
-
+ break
Bumped(var/atom/movable/M)
- if(target.z > z && istype(src, /obj/multiz/stairs/active) && !locate(/obj/multiz/stairs) in M.loc)
- return //If on bottom, only let them go up stairs if they've moved to the entry tile first.
- //If it's the top, they can fall down just fine.
-
- if(!target || !istype(target.loc, /turf))
- del src
-
- if(ismob(M) && M:client)
- M:client.moving = 1
- M.Move(target.loc)
- if (ismob(M) && M:client)
- M:client.moving = 0
-
- Click()
- if(!istype(usr,/mob/dead/observer))
- return ..()
- if(!target || !istype(target.loc, /turf))
- del src
- usr.client.moving = 1
- usr.Move(target.loc)
- usr.client.moving = 0
\ No newline at end of file
+ if(connected && target && istype(src, /obj/multiz/stairs) && locate(/obj/multiz/stairs) in M.loc)
+ var/obj/multiz/stairs/Con = locate(/obj/multiz/stairs) in M.loc
+ if(Con == src.connected) //make sure the atom enters from the approriate lower stairs tile
+ M.Move(target)
+ return
diff --git a/code/TriDimension/Turfs.dm b/code/TriDimension/Turfs.dm
index 1e49e4dc80e..2f99b6fd415 100644
--- a/code/TriDimension/Turfs.dm
+++ b/code/TriDimension/Turfs.dm
@@ -1,27 +1,3 @@
-atom/movable/var/list/adjacent_z_levels
-atom/movable/var/archived_z_level
-
-atom/movable/Move() //Hackish
-
- if(adjacent_z_levels && adjacent_z_levels["up"])
- var/turf/above_me = locate(x,y,adjacent_z_levels["up"])
- if(istype(above_me, /turf/simulated/floor/open))
- above_me:RemoveImage(src)
-
- . = ..()
-
- if(archived_z_level != z)
- archived_z_level = z
- if(z in levels_3d)
- adjacent_z_levels = global_adjacent_z_levels["[z]"]
- else
- adjacent_z_levels = null
-
- if(adjacent_z_levels && adjacent_z_levels["up"])
- var/turf/above_me = locate(x,y,adjacent_z_levels["up"])
- if(istype(above_me, /turf/simulated/floor/open))
- above_me:AddImage(src)
-
/turf/simulated/floor/open
name = "open space"
intact = 0
@@ -31,66 +7,109 @@ atom/movable/Move() //Hackish
var/icon/darkoverlays = null
var/turf/floorbelow
var/list/overlay_references
- mouse_opacity = 2
New()
..()
- spawn(1)
- if(!(z in levels_3d))
- ReplaceWithSpace()
- var/list/adjacent_to_me = global_adjacent_z_levels["[z]"]
- if(!("down" in adjacent_to_me))
- ReplaceWithSpace()
-
- floorbelow = locate(x, y, adjacent_to_me["down"])
- if(floorbelow)
- if(!istype(floorbelow,/turf))
- del src
- else if(floorbelow.density)
- ReplaceWithPlating()
- else
- set_up()
- else
- ReplaceWithSpace()
-
+ getbelow()
+ return
Enter(var/atom/movable/AM)
if (..()) //TODO make this check if gravity is active (future use) - Sukasa
spawn(1)
+ // only fall down in defined areas (read: areas with artificial gravitiy)
+ if(!floorbelow) //make sure that there is actually something below
+ if(!getbelow())
+ return
if(AM)
- AM.Move(floorbelow)
- if (istype(AM, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = AM
- var/damage = rand(5,15)
- H.apply_damage(2*damage, BRUTE, "head")
- H.apply_damage(2*damage, BRUTE, "chest")
- H.apply_damage(0.5*damage, BRUTE, "l_leg")
- H.apply_damage(0.5*damage, BRUTE, "r_leg")
- H.apply_damage(0.5*damage, BRUTE, "l_arm")
- H.apply_damage(0.5*damage, BRUTE, "r_arm")
- H:weakened = max(H:weakened,2)
- H:updatehealth()
+ var/area/areacheck = get_area(src)
+ var/blocked = 0
+ var/soft = 0
+ for(var/atom/A in floorbelow.contents)
+ if(A.density)
+ blocked = 1
+ break
+ if(istype(A, /obj/machinery/atmospherics/pipe/zpipe/up) && istype(AM,/obj/item/pipe))
+ blocked = 1
+ break
+ if(istype(A, /obj/structure/disposalpipe/up) && istype(AM,/obj/item/pipe))
+ blocked = 1
+ break
+ if(istype(A, /obj/multiz/stairs))
+ soft = 1
+ //dont break here, since we still need to be sure that it isnt blocked
+
+ if (soft || (!blocked && !(areacheck.name == "Space")))
+ AM.Move(floorbelow)
+ if (!soft && istype(AM, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = AM
+ var/damage = 5
+ H.apply_damage(min(rand(-damage,damage),0), BRUTE, "head")
+ H.apply_damage(min(rand(-damage,damage),0), BRUTE, "chest")
+ H.apply_damage(min(rand(-damage,damage),0), BRUTE, "l_leg")
+ H.apply_damage(min(rand(-damage,damage),0), BRUTE, "r_leg")
+ H.apply_damage(min(rand(-damage,damage),0), BRUTE, "l_arm")
+ H.apply_damage(min(rand(-damage,damage),0), BRUTE, "r_arm")
+ H:weakened = max(H:weakened,2)
+ H:updatehealth()
return ..()
- attackby()
- return //nothing
+/turf/simulated/floor/open/proc/getbelow()
+ var/turf/controlerlocation = locate(1, 1, z)
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ // check if there is something to draw below
+ if(!controler.down)
+ src.ChangeTurf(/turf/space)
+ return 0
+ else
+ floorbelow = locate(src.x, src.y, controler.down_target)
+ return 1
+ return 1
- proc/set_up() //Update the overlays to make the openspace turf show what's down a level
- if(!overlay_references)
- overlay_references = list()
- if(!floorbelow) return
- overlays += floorbelow
- for(var/obj/o in floorbelow)
- var/image/o_img = image(o, dir=o.dir, layer = TURF_LAYER+0.05*o.layer)
- overlays += o_img
- overlay_references[o] = o_img
+// override to make sure nothing is hidden
+/turf/simulated/floor/open/levelupdate()
+ for(var/obj/O in src)
+ if(O.level == 1)
+ O.hide(0)
- proc/AddImage(var/atom/movable/o)
- var/o_img = image(o, dir=o.dir, layer = TURF_LAYER+0.05*o.layer)
- overlays += o_img
- overlay_references[o] = o_img
+//overwrite the attackby of space to transform it to openspace if necessary
+/turf/space/attackby(obj/item/C as obj, mob/user as mob)
+ if (istype(C, /obj/item/weapon/cable_coil))
+ var/turf/simulated/floor/open/W = src.ChangeTurf(/turf/simulated/floor/open)
+ W.attackby(C, user)
+ return
+ ..()
- proc/RemoveImage(var/atom/movable/o)
- var/o_img = overlay_references[o]
- overlays -= o_img
- overlay_references -= o
\ No newline at end of file
+/turf/simulated/floor/open/ex_act(severity)
+ // cant destroy empty space with an ordinary bomb
+ return
+
+/turf/simulated/floor/open/attackby(obj/item/C as obj, mob/user as mob)
+ (..)
+ if (istype(C, /obj/item/weapon/cable_coil))
+ var/obj/item/weapon/cable_coil/cable = C
+ cable.turf_place(src, user)
+ return
+
+ if (istype(C, /obj/item/stack/rods))
+ var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
+ if(L)
+ return
+ var/obj/item/stack/rods/R = C
+ user << "\blue Constructing support lattice ..."
+ playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
+ ReplaceWithLattice()
+ R.use(1)
+ return
+
+ if (istype(C, /obj/item/stack/tile/plasteel))
+ var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
+ if(L)
+ var/obj/item/stack/tile/plasteel/S = C
+ del(L)
+ playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
+ S.build(src)
+ S.use(1)
+ return
+ else
+ user << "\red The plating is going to need some support."
+ return
diff --git a/code/TriDimension/controler.dm b/code/TriDimension/controler.dm
new file mode 100644
index 00000000000..59915797385
--- /dev/null
+++ b/code/TriDimension/controler.dm
@@ -0,0 +1,263 @@
+/obj/effect/landmark/zcontroler
+ name = "Z-Level Controler"
+ var/initialized = 0 // when set to 1, turfs will report to the controler
+ var/up = 0 // 1 allows up movement
+ var/up_target = 0 // the Z-level that is above the current one
+ var/down = 0 // 1 allows down movement
+ var/down_target = 0 // the Z-level that is below the current one
+
+ var/list/slow = list()
+ var/list/normal = list()
+ var/list/fast = list()
+
+ var/slow_time
+ var/normal_time
+ var/fast_time
+
+/obj/effect/landmark/zcontroler/New()
+ ..()
+ for (var/turf/T in world)
+ if (T.z == z)
+ fast += T
+ slow_time = world.time + 3000
+ normal_time = world.time + 600
+ fast_time = world.time + 10
+
+ processing_objects.Add(src)
+
+ initialized = 1
+ return 1
+
+/obj/effect/landmark/zcontroler/Del()
+ processing_objects.Remove(src)
+ return
+
+/obj/effect/landmark/zcontroler/process()
+ if (world.time > fast_time)
+ calc(fast)
+ fast_time = world.time + 10
+
+ if (world.time > normal_time)
+ calc(normal)
+ normal_time = world.time + 600
+
+/* if (world.time > slow_time)
+ calc(slow)
+ slow_time = world.time + 3000 */
+ return
+
+/obj/effect/landmark/zcontroler/proc/add(var/list/L, var/I, var/transfer)
+ while (L.len)
+ var/turf/T = pick(L)
+
+ L -= T
+ slow -= T
+ normal -= T
+ fast -= T
+
+ if(!T || !istype(T, /turf))
+ continue
+
+ switch (I)
+ if(1) slow += T
+ if(2) normal += T
+ if(3) fast += T
+
+ if(transfer > 0)
+ if(up)
+ var/turf/controler_up = locate(1, 1, up_target)
+ for(var/obj/effect/landmark/zcontroler/c_up in controler_up)
+ var/list/temp = list()
+ temp += locate(T.x, T.y, up_target)
+ c_up.add(temp, I, transfer-1)
+
+ if(down)
+ var/turf/controler_down = locate(1, 1, down_target)
+ for(var/obj/effect/landmark/zcontroler/c_down in controler_down)
+ var/list/temp = list()
+ temp += locate(T.x, T.y, down_target)
+ c_down.add(temp, I, transfer-1)
+ return
+
+/turf
+ var/list/z_overlays = list()
+
+/turf/New()
+ ..()
+
+ var/turf/controler = locate(1, 1, z)
+ for(var/obj/effect/landmark/zcontroler/c in controler)
+ if(c.initialized)
+ var/list/turf = list()
+ turf += src
+ c.add(turf,3,1)
+
+/turf/space/New()
+ ..()
+
+ var/turf/controler = locate(1, 1, z)
+ for(var/obj/effect/landmark/zcontroler/c in controler)
+ if(c.initialized)
+ var/list/turf = list()
+ turf += src
+ c.add(turf,3,1)
+
+atom/movable/Move() //Hackish
+ . = ..()
+
+ var/turf/controlerlocation = locate(1, 1, src.z)
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ if(controler.up || controler.down)
+ var/list/temp = list()
+ temp += locate(src.x, src.y, src.z)
+ controler.add(temp,3,1)
+
+/obj/effect/landmark/zcontroler/proc/calc(var/list/L)
+ var/list/slowholder = list()
+ var/list/normalholder = list()
+ var/list/fastholder = list()
+ var/new_list
+
+ while(L.len)
+ var/turf/T = pick(L)
+ new_list = 0
+
+ if(!T || !istype(T, /turf))
+ L -= T
+ continue
+
+ T.overlays -= T.z_overlays
+ T.z_overlays -= T.z_overlays
+
+ if(down && (istype(T, /turf/space) || istype(T, /turf/simulated/floor/open)))
+ var/turf/below = locate(T.x, T.y, down_target)
+ if(below)
+ if(!(istype(below, /turf/space) || istype(below, /turf/simulated/floor/open)))
+ var/image/t_img = list()
+ new_list = 1
+
+ var/image/temp = image(below, dir=below.dir, layer = TURF_LAYER + 0.04)
+
+ temp.color = rgb(127,127,127)
+ temp.overlays += below.overlays
+ t_img += temp
+ T.overlays += t_img
+ T.z_overlays += t_img
+
+ // get objects
+ var/image/o_img = list()
+ for(var/obj/o in below)
+ // ingore objects that have any form of invisibility
+ if(o.invisibility) continue
+ new_list = 2
+ var/image/temp2 = image(o, dir=o.dir, layer = TURF_LAYER+0.05*o.layer)
+ temp2.color = rgb(127,127,127)
+ temp2.overlays += o.overlays
+ o_img += temp2
+ // you need to add a list to .overlays or it will not display any because space
+ T.overlays += o_img
+ T.z_overlays += o_img
+
+ // get mobs
+ var/image/m_img = list()
+ for(var/mob/m in below)
+ // ingore mobs that have any form of invisibility
+ if(m.invisibility) continue
+ // only add this tile to fastprocessing if there is a living mob, not a dead one
+ if(istype(m, /mob/living)) new_list = 3
+ var/image/temp2 = image(m, dir=m.dir, layer = TURF_LAYER+0.05*m.layer)
+ temp2.color = rgb(127,127,127)
+ temp2.overlays += m.overlays
+ m_img += temp2
+ // you need to add a list to .overlays or it will not display any because space
+ T.overlays += m_img
+ T.z_overlays += m_img
+
+ T.overlays -= below.z_overlays
+ T.z_overlays -= below.z_overlays
+
+ // this is sadly impossible to use right now
+ // the overlay is always opaque to mouseclicks and thus prevents interactions with everything except the turf
+ /*if(up)
+ var/turf/above = locate(T.x, T.y, up_target)
+ if(above)
+ var/eligeable = 0
+ for(var/d in cardinal)
+ var/turf/mT = get_step(above,d)
+ if(istype(mT, /turf/space) || istype(mT, /turf/simulated/floor/open))
+ eligeable = 1
+ /*if(mT.opacity == 0)
+ for(var/f in cardinal)
+ var/turf/nT = get_step(mT,f)
+ if(istype(nT, /turf/space) || istype(nT, /turf/simulated/floor/open))
+ eligeable = 1*/
+ if(istype(above, /turf/space) || istype(above, /turf/simulated/floor/open)) eligeable = 1
+ if(eligeable == 1)
+ if(!(istype(above, /turf/space) || istype(above, /turf/simulated/floor/open)))
+ var/image/t_img = list()
+ if(new_list < 1) new_list = 1
+
+ above.overlays -= above.z_overlays
+ var/image/temp = image(above, dir=above.dir, layer = 5 + 0.04)
+ above.overlays += above.z_overlays
+
+ temp.alpha = 100
+ temp.overlays += above.overlays
+ temp.overlays -= above.z_overlays
+ t_img += temp
+ T.overlays += t_img
+ T.z_overlays += t_img
+
+ // get objects
+ var/image/o_img = list()
+ for(var/obj/o in above)
+ // ingore objects that have any form of invisibility
+ if(o.invisibility) continue
+ if(new_list < 2) new_list = 2
+ var/image/temp2 = image(o, dir=o.dir, layer = 5+0.05*o.layer)
+ temp2.alpha = 100
+ temp2.overlays += o.overlays
+ o_img += temp2
+ // you need to add a list to .overlays or it will not display any because space
+ T.overlays += o_img
+ T.z_overlays += o_img
+
+ // get mobs
+ var/image/m_img = list()
+ for(var/mob/m in above)
+ // ingore mobs that have any form of invisibility
+ if(m.invisibility) continue
+ // only add this tile to fastprocessing if there is a living mob, not a dead one
+ if(istype(m, /mob/living) && new_list < 3) new_list = 3
+ var/image/temp2 = image(m, dir=m.dir, layer = 5+0.05*m.layer)
+ temp2.alpha = 100
+ temp2.overlays += m.overlays
+ m_img += temp2
+ // you need to add a list to .overlays or it will not display any because space
+ T.overlays += m_img
+ T.z_overlays += m_img
+
+ T.overlays -= above.z_overlays
+ T.z_overlays -= above.z_overlays*/
+
+ L -= T
+
+ if(new_list == 1)
+ slowholder += T
+ if(new_list == 2)
+ normalholder += T
+ if(new_list == 3)
+ fastholder += T
+ for(var/d in cardinal)
+ var/turf/mT = get_step(T,d)
+ if(!(mT in fastholder))
+ fastholder += mT
+ for(var/f in cardinal)
+ var/turf/nT = get_step(mT,f)
+ if(!(nT in fastholder))
+ fastholder += nT
+
+ add(slowholder,1, 0)
+ add(normalholder, 2, 0)
+ add(fastholder, 3, 0)
+ return
diff --git a/code/ZAS/Functions.dm b/code/ZAS/Functions.dm
index 3037e13f412..4cefd09b74c 100644
--- a/code/ZAS/Functions.dm
+++ b/code/ZAS/Functions.dm
@@ -11,6 +11,12 @@ proc/FloodFill(turf/simulated/start)
var/list/open = list(start)
//The list of tiles which have been evaulated.
var/list/closed = list()
+/////// Z-Level stuff
+ //List of all space tiles bordering the zone
+ var/list/list_space = list()
+ //List of all Z-Levels of the zone where it borders space
+ var/list/z_space = list()
+/////// Z-Level stuff
//Loop through the turfs in the open list in order to find which adjacent turfs should be added to the zone.
while(open.len)
@@ -67,10 +73,75 @@ proc/FloodFill(turf/simulated/start)
//If it cannot connect either to the north or west, connect it!
closed += O
+/////// Z-Level stuff
+ if(istype(O,/turf/space))
+ if(!(O in list_space))
+ list_space += O
+ if(!(O.z in z_space))
+ z_space += O.z
+
+ // handle Z-level connections
+ var/turf/controlerlocation = locate(1, 1, T.z)
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ // connect upwards
+ if(controler.up)
+ var/turf/above_me = locate(T.x, T.y, controler.up_target)
+ // add the turf above this
+ if(istype(above_me, /turf/simulated/floor/open) && !(above_me in open) && !(above_me in closed))
+ open += above_me
+
+ if(istype(above_me,/turf/space))
+ if(!(above_me in list_space))
+ list_space += above_me
+ if(!(above_me.z in z_space))
+ z_space += above_me.z
+ // connect downwards
+ if(controler.down && istype(T, /turf/simulated/floor/open))
+ var/turf/below_me = locate(T.x, T.y, controler.down_target)
+ // add the turf below this
+ if(!(below_me in open) && !(below_me in closed))
+ open += below_me
+/////// Z-Level stuff
+
//This tile is now evaluated, and can be moved to the list of evaluated tiles.
open -= T
closed += T
+/////// Z-Level stuff
+ // once the zone is done, check if there is space that needs to be changed to open space
+ if(!open.len)
+ var/list/temp = list()
+ while(list_space.len)
+ var/turf/S = pick(list_space)
+ //check if the zone has any space borders below the evaluated space tile
+ //if there is some, we dont need to make open_space since the zone can vent and the zone above can vent
+ //through the evaluated tile
+ //if there is none, the zone can connect upwards to either vent from there or connect with the zone there
+ //also check if the turf below the space is actually part of this zone to prevent the edge tiles from transforming
+ var/turf/controlerloc = locate(1, 1, S.z)
+ for(var/obj/effect/landmark/zcontroler/controler in controlerloc)
+ if(controler.down)
+ var/turf/below = locate(S.x, S.y, controler.down_target)
+ if(!((S.z - 1) in z_space) && below in closed)
+ open += S.ChangeTurf(/turf/simulated/floor/open)
+ list_space -= S
+ else
+ list_space -= S
+ temp += S
+ else
+ list_space -= S
+ temp += S
+ // make sure the turf is removed from the list
+ list_space -= S
+ z_space -= z_space
+ while(temp.len)
+ var/turf/S = pick(temp)
+ if(!(S.z in z_space))
+ z_space += S.z
+ list_space += S
+ temp -= S
+/////// Z-Level stuff
+
return closed
diff --git a/code/ZAS/ZAS_Zones.dm b/code/ZAS/ZAS_Zones.dm
index 1d92062e25d..f6a3327ff23 100644
--- a/code/ZAS/ZAS_Zones.dm
+++ b/code/ZAS/ZAS_Zones.dm
@@ -151,6 +151,13 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs
air.group_multiplier++
T.zone = src
+
+///// Z-Level Stuff
+ // also add the tile below it if its open space
+ if(istype(T, /turf/simulated/floor/open))
+ var/turf/simulated/floor/open/T2 = T
+ src.AddTurf(T2.floorbelow)
+///// Z-Level Stuff
else
if(!unsimulated_tiles)
@@ -773,6 +780,32 @@ zone/proc/Rebuild()
if(adjacent_id && (!lowest_id || adjacent_id < lowest_id))
lowest_id = adjacent_id
+/////// Z-Level stuff
+ var/turf/controlerlocation = locate(1, 1, current.z)
+ for(var/obj/effect/landmark/zcontroler/controler in controlerlocation)
+ // upwards
+ if(controler.up)
+ var/turf/simulated/adjacent = locate(current.x, current.y, controler.up_target)
+
+ if(adjacent in turfs && istype(adjacent, /turf/simulated/floor/open))
+ current_adjacents += adjacent
+ adjacent_id = turfs[adjacent]
+
+ if(adjacent_id && (!lowest_id || adjacent_id < lowest_id))
+ lowest_id = adjacent_id
+
+ // downwards
+ if(controler.down && istype(current, /turf/simulated/floor/open))
+ var/turf/simulated/adjacent = locate(current.x, current.y, controler.down_target)
+
+ if(adjacent in turfs)
+ current_adjacents += adjacent
+ adjacent_id = turfs[adjacent]
+
+ if(adjacent_id && (!lowest_id || adjacent_id < lowest_id))
+ lowest_id = adjacent_id
+/////// Z-Level stuff
+
if(!lowest_id)
lowest_id = current_identifier++
identical_ids += lowest_id
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 1babba054e6..72aa31ccee0 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -23,6 +23,10 @@ Buildable meters
#define PIPE_MTVALVE 18
#define PIPE_MANIFOLD4W 19
#define PIPE_CAP 20
+///// Z-Level stuff
+#define PIPE_UP 21
+#define PIPE_DOWN 22
+///// Z-Level stuff
/obj/item/pipe
name = "pipe"
@@ -84,6 +88,12 @@ Buildable meters
src.pipe_type = PIPE_MANIFOLD4W
else if(istype(make_from, /obj/machinery/atmospherics/pipe/cap))
src.pipe_type = PIPE_CAP
+///// Z-Level stuff
+ else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/up))
+ src.pipe_type = PIPE_UP
+ else if(istype(make_from, /obj/machinery/atmospherics/pipe/zpipe/down))
+ src.pipe_type = PIPE_DOWN
+///// Z-Level stuff
else
src.pipe_type = pipe_type
src.dir = dir
@@ -117,6 +127,10 @@ Buildable meters
"t-valve", \
"4-way manifold", \
"pipe cap", \
+///// Z-Level stuff
+ "pipe up", \
+ "pipe down", \
+///// Z-Level stuff
)
name = nlist[pipe_type+1] + " fitting"
var/list/islist = list( \
@@ -141,6 +155,10 @@ Buildable meters
"mtvalve", \
"manifold4w", \
"cap", \
+///// Z-Level stuff
+ "cap", \
+ "cap", \
+///// Z-Level stuff
)
icon_state = islist[pipe_type + 1]
@@ -213,6 +231,10 @@ Buildable meters
return dir|flip|cw
if(PIPE_CAP)
return flip
+///// Z-Level stuff
+ if(PIPE_UP,PIPE_DOWN)
+ return dir
+///// Z-Level stuff
return 0
/obj/item/pipe/proc/get_pdir() //endpoints for regular pipes
@@ -348,7 +370,7 @@ Buildable meters
if (M.node3)
M.node3.initialize()
M.node3.build_network()
-
+
if(PIPE_MANIFOLD4W) //4-way manifold
var/obj/machinery/atmospherics/pipe/manifold4w/M = new( src.loc )
M.dir = dir
@@ -515,7 +537,7 @@ Buildable meters
if (P.node2)
P.node2.initialize()
P.node2.build_network()
-
+
if(PIPE_MTVALVE) //manual t-valve
var/obj/machinery/atmospherics/tvalve/V = new(src.loc)
V.dir = dir
@@ -535,7 +557,7 @@ Buildable meters
if (V.node3)
V.node3.initialize()
V.node3.build_network()
-
+
if(PIPE_CAP)
var/obj/machinery/atmospherics/pipe/cap/C = new(src.loc)
C.dir = dir
@@ -593,6 +615,40 @@ Buildable meters
if (C.node)
C.node.initialize()
C.node.build_network()
+///// Z-Level stuff
+ if(PIPE_UP) //volume pump
+ var/obj/machinery/atmospherics/pipe/zpipe/up/P = new(src.loc)
+ P.dir = dir
+ P.initialize_directions = pipe_dir
+ if (pipename)
+ P.name = pipename
+ var/turf/T = P.loc
+ P.level = T.intact ? 2 : 1
+ P.initialize()
+ P.build_network()
+ if (P.node1)
+ P.node1.initialize()
+ P.node1.build_network()
+ if (P.node2)
+ P.node2.initialize()
+ P.node2.build_network()
+ if(PIPE_DOWN) //volume pump
+ var/obj/machinery/atmospherics/pipe/zpipe/down/P = new(src.loc)
+ P.dir = dir
+ P.initialize_directions = pipe_dir
+ if (pipename)
+ P.name = pipename
+ var/turf/T = P.loc
+ P.level = T.intact ? 2 : 1
+ P.initialize()
+ P.build_network()
+ if (P.node1)
+ P.node1.initialize()
+ P.node1.build_network()
+ if (P.node2)
+ P.node2.initialize()
+ P.node2.build_network()
+///// Z-Level stuff
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user.visible_message( \
@@ -649,4 +705,4 @@ Buildable meters
#undef PIPE_VOLUME_PUMP
#undef PIPE_OUTLET_INJECT
#undef PIPE_MTVALVE
-//#undef PIPE_MANIFOLD4W
\ No newline at end of file
+//#undef PIPE_MANIFOLD4W
diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm
index e883d4d07d1..bf6233f4d47 100644
--- a/code/game/machinery/pipe/pipe_dispenser.dm
+++ b/code/game/machinery/pipe/pipe_dispenser.dm
@@ -13,6 +13,7 @@
/obj/machinery/pipedispenser/attack_hand(user as mob)
if(..())
return
+///// Z-Level stuff
var/dat = {"
Regular pipes:
Pipe
@@ -22,6 +23,8 @@
Pipe Cap
4-Way Manifold
Manual T-Valve
+upward Pipe
+downward Pipe
Devices:
Connector
Unary Vent
@@ -42,6 +45,7 @@
Bent Pipe
"}
+///// Z-Level stuff
//What number the make points to is in the define # at the top of construction.dm in same folder
user << browse("