diff --git a/baystation12.dme b/baystation12.dme
index a780bc568a6..c7b1de5ca8e 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -194,6 +194,7 @@
#include "code\ATMOSPHERICS\he_pipes.dm"
#include "code\ATMOSPHERICS\pipes.dm"
#include "code\ATMOSPHERICS\components\portables_connector.dm"
+#include "code\ATMOSPHERICS\components\tvalve.dm"
#include "code\ATMOSPHERICS\components\valve.dm"
#include "code\ATMOSPHERICS\components\binary_devices\binary_atmos_base.dm"
#include "code\ATMOSPHERICS\components\binary_devices\circulator.dm"
diff --git a/code/ATMOSPHERICS/components/tvalve.dm b/code/ATMOSPHERICS/components/tvalve.dm
new file mode 100644
index 00000000000..cc5d8d4f31a
--- /dev/null
+++ b/code/ATMOSPHERICS/components/tvalve.dm
@@ -0,0 +1,337 @@
+obj/machinery/atmospherics/tvalve
+ icon = 'valve.dmi'
+ icon_state = "tvalve0"
+
+ name = "manual switching valve"
+ desc = "A pipe valve"
+
+ dir = SOUTH
+ initialize_directions = SOUTH|NORTH|WEST
+
+ var/state = 0 // 0 = go straight, 1 = go to side
+
+ // like a trinary component, node1 is input, node2 is side output, node3 is straight output
+ var/obj/machinery/atmospherics/node1
+ var/obj/machinery/atmospherics/node2
+ var/obj/machinery/atmospherics/node3
+
+ var/datum/pipe_network/network_node1
+ var/datum/pipe_network/network_node2
+ var/datum/pipe_network/network_node3
+
+ update_icon(animation)
+ if(animation)
+ flick("tvalve[src.state][!src.state]",src)
+ else
+ icon_state = "tvalve[state]"
+
+ New()
+ switch(dir)
+ if(NORTH)
+ initialize_directions = SOUTH|NORTH|EAST
+ if(SOUTH)
+ initialize_directions = NORTH|SOUTH|WEST
+ if(EAST)
+ initialize_directions = WEST|EAST|SOUTH
+ if(WEST)
+ initialize_directions = EAST|WEST|NORTH
+ ..()
+
+ network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+ if(reference == node1)
+ network_node1 = new_network
+ if(state)
+ network_node2 = new_network
+ else
+ network_node3 = new_network
+ else if(reference == node2)
+ network_node2 = new_network
+ if(state)
+ network_node1 = new_network
+ else if(reference == node3)
+ network_node3 = new_network
+ if(!state)
+ network_node1 = new_network
+
+ if(new_network.normal_members.Find(src))
+ return 0
+
+ new_network.normal_members += src
+
+ if(state)
+ if(reference == node1)
+ if(node2)
+ return node2.network_expand(new_network, src)
+ else if(reference == node2)
+ if(node1)
+ return node1.network_expand(new_network, src)
+ else
+ if(reference == node1)
+ if(node3)
+ return node3.network_expand(new_network, src)
+ else if(reference == node3)
+ if(node1)
+ return node1.network_expand(new_network, src)
+
+ return null
+
+ Del()
+ loc = null
+
+ if(node1)
+ node1.disconnect(src)
+ del(network_node1)
+ if(node2)
+ node2.disconnect(src)
+ del(network_node2)
+ if(node3)
+ node3.disconnect(src)
+ del(network_node3)
+
+ node1 = null
+ node2 = null
+ node3 = null
+
+ ..()
+
+ proc/go_to_side()
+
+ if(state) return 0
+
+ state = 1
+ update_icon()
+
+ if(network_node1)
+ del(network_node1)
+ if(network_node3)
+ del(network_node3)
+ build_network()
+
+ if(network_node1&&network_node2)
+ network_node1.merge(network_node2)
+ network_node2 = network_node1
+
+ if(network_node1)
+ network_node1.update = 1
+ else if(network_node2)
+ network_node2.update = 1
+
+ return 1
+
+ proc/go_straight()
+
+ if(!state)
+ return 0
+
+ state = 0
+ update_icon()
+
+ if(network_node1)
+ del(network_node1)
+ if(network_node2)
+ del(network_node2)
+ build_network()
+
+ if(network_node1&&network_node3)
+ network_node1.merge(network_node3)
+ network_node3 = network_node1
+
+ if(network_node1)
+ network_node1.update = 1
+ else if(network_node3)
+ network_node3.update = 1
+
+ return 1
+
+ attack_ai(mob/user as mob)
+ return
+
+ attack_paw(mob/user as mob)
+ return attack_hand(user)
+
+ attack_hand(mob/user as mob)
+ src.add_fingerprint(usr)
+ update_icon(1)
+ sleep(10)
+ if (src.state)
+ src.go_straight()
+ else
+ src.go_to_side()
+
+ process()
+ ..()
+ machines.Remove(src)
+
+/* if(open && (!node1 || !node2))
+ close()
+ if(!node1)
+ if(!nodealert)
+ //world << "Missing node from [src] at [src.x],[src.y],[src.z]"
+ nodealert = 1
+ else if (!node2)
+ if(!nodealert)
+ //world << "Missing node from [src] at [src.x],[src.y],[src.z]"
+ nodealert = 1
+ else if (nodealert)
+ nodealert = 0
+*/
+
+ return
+
+ initialize()
+ var/node1_dir
+ var/node2_dir
+ var/node3_dir
+
+ node1_dir = turn(dir, 180)
+ node2_dir = turn(dir, -90)
+ node3_dir = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
+ if(target.initialize_directions & get_dir(target,src))
+ node1 = target
+ break
+ for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
+ if(target.initialize_directions & get_dir(target,src))
+ node2 = target
+ break
+ for(var/obj/machinery/atmospherics/target in get_step(src,node3_dir))
+ if(target.initialize_directions & get_dir(target,src))
+ node3 = target
+ break
+
+ build_network()
+ if(!network_node1 && node1)
+ network_node1 = new /datum/pipe_network()
+ network_node1.normal_members += src
+ network_node1.build_network(node1, src)
+
+ if(!network_node2 && node2)
+ network_node2 = new /datum/pipe_network()
+ network_node2.normal_members += src
+ network_node2.build_network(node2, src)
+
+ if(!network_node3 && node3)
+ network_node3 = new /datum/pipe_network()
+ network_node3.normal_members += src
+ network_node3.build_network(node3, src)
+
+
+ return_network(obj/machinery/atmospherics/reference)
+ build_network()
+
+ if(reference==node1)
+ return network_node1
+
+ if(reference==node2)
+ return network_node2
+
+ if(reference==node3)
+ return network_node3
+
+ return null
+
+ reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
+ if(network_node1 == old_network)
+ network_node1 = new_network
+ if(network_node2 == old_network)
+ network_node2 = new_network
+ if(network_node3 == old_network)
+ network_node3 = new_network
+
+ return 1
+
+ return_network_air(datum/network/reference)
+ return null
+
+ disconnect(obj/machinery/atmospherics/reference)
+ if(reference==node1)
+ del(network_node1)
+ node1 = null
+
+ else if(reference==node2)
+ del(network_node2)
+ node2 = null
+
+ else if(reference==node3)
+ del(network_node3)
+ node2 = null
+
+ return null
+
+ digital // can be controlled by AI
+ name = "digital switching valve"
+ desc = "A digitally controlled valve."
+ icon = 'digital_valve.dmi'
+
+ attack_ai(mob/user as mob)
+ return src.attack_hand(user)
+
+ attack_hand(mob/user as mob)
+ if(!src.allowed(user))
+ user << "\red Access denied."
+ return
+ ..()
+
+ //Radio remote control
+
+ proc
+ set_frequency(new_frequency)
+ radio_controller.remove_object(src, frequency)
+ frequency = new_frequency
+ if(frequency)
+ radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
+
+ var/frequency = 0
+ var/id = null
+ var/datum/radio_frequency/radio_connection
+
+ initialize()
+ ..()
+ if(frequency)
+ set_frequency(frequency)
+
+ receive_signal(datum/signal/signal)
+ if(!signal.data["tag"] || (signal.data["tag"] != id))
+ return 0
+
+ switch(signal.data["command"])
+ if("valve_open")
+ if(!state)
+ go_to_side()
+
+ if("valve_close")
+ if(state)
+ go_straight()
+
+ if("valve_toggle")
+ if(state)
+ go_straight()
+ else
+ go_to_side()
+
+ attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+ if (!istype(W, /obj/item/weapon/wrench))
+ return ..()
+ if (istype(src, /obj/machinery/atmospherics/tvalve/digital))
+ user << "\red You cannot unwrench this [src], it's too complicated."
+ return 1
+ var/turf/T = src.loc
+ if (level==1 && isturf(T) && T.intact)
+ user << "\red You must remove the plating first."
+ return 1
+ var/datum/gas_mixture/int_air = return_air()
+ var/datum/gas_mixture/env_air = loc.return_air()
+ if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
+ user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
+ add_fingerprint(user)
+ return 1
+ playsound(src.loc, 'Ratchet.ogg', 50, 1)
+ user << "\blue You begin to unfasten \the [src]..."
+ if (do_after(user, 40))
+ user.visible_message( \
+ "[user] unfastens \the [src].", \
+ "\blue You have unfastened \the [src].", \
+ "You hear ratchet.")
+ new /obj/item/pipe(loc, make_from=src)
+ del(src)
diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm
index 8964822c2fd..50a2202304b 100644
--- a/code/ATMOSPHERICS/pipes.dm
+++ b/code/ATMOSPHERICS/pipes.dm
@@ -800,6 +800,202 @@ obj/machinery/atmospherics/pipe
level = 1
icon_state = "manifold-f"
+ manifold4w
+ icon = 'pipe_manifold.dmi'
+ icon_state = "manifold4w-f"
+
+ name = "4-way pipe manifold"
+ desc = "A manifold composed of regular pipes"
+
+ volume = 140
+
+ dir = SOUTH
+ initialize_directions = EAST|NORTH|WEST|SOUTH
+
+ var/obj/machinery/atmospherics/node1
+ var/obj/machinery/atmospherics/node2
+ var/obj/machinery/atmospherics/node3
+ var/obj/machinery/atmospherics/node4
+
+ level = 1
+
+ hide(var/i)
+ if(level == 1 && istype(loc, /turf/simulated))
+ invisibility = i ? 101 : 0
+ update_icon()
+
+ pipeline_expansion()
+ return list(node1, node2, node3, node4)
+
+ process()
+ if(!parent)
+ ..()
+ else
+ machines.Remove(src)
+/*
+ if(!node1)
+ parent.mingle_with_turf(loc, 70)
+ if(!nodealert)
+ //world << "Missing node from [src] at [src.x],[src.y],[src.z]"
+ nodealert = 1
+ else if(!node2)
+ parent.mingle_with_turf(loc, 70)
+ if(!nodealert)
+ //world << "Missing node from [src] at [src.x],[src.y],[src.z]"
+ nodealert = 1
+ else if(!node3)
+ parent.mingle_with_turf(loc, 70)
+ if(!nodealert)
+ //world << "Missing node from [src] at [src.x],[src.y],[src.z]"
+ nodealert = 1
+ else if (nodealert)
+ nodealert = 0
+*/
+ Del()
+ if(node1)
+ node1.disconnect(src)
+ if(node2)
+ node2.disconnect(src)
+ if(node3)
+ node3.disconnect(src)
+ if(node4)
+ node4.disconnect(src)
+
+ ..()
+
+ 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
+
+ if(reference == node3)
+ if(istype(node3, /obj/machinery/atmospherics/pipe))
+ del(parent)
+ node3 = null
+
+ if(reference == node4)
+ if(istype(node4, /obj/machinery/atmospherics/pipe))
+ del(parent)
+ node3 = null
+
+ update_icon()
+
+ ..()
+
+ update_icon()
+ overlays = new()
+ if(node1&&node2&&node3&&node4)
+ var/C = ""
+ switch(color)
+ if ("red") C = "-r"
+ if ("blue") C = "-b"
+ if ("cyan") C = "-c"
+ if ("green") C = "-g"
+ if ("yellow") C = "-y"
+ if ("purple") C = "-p"
+ icon_state = "manifold4w[C][invisibility ? "-f" : ""]"
+
+ else
+ icon_state = "manifold4w_ex"
+ var/icon/con = new/icon('pipe_manifold.dmi',"manifold4w_con")
+
+ if(node1)
+ overlays += new/image(con,dir=1)
+ if(node2)
+ overlays += new/image(con,dir=2)
+ if(node3)
+ overlays += new/image(con,dir=4)
+ if(node4)
+ overlays += new/image(con,dir=8)
+
+ if(!node1 && !node2 && !node3 && !node4)
+ del(src)
+ return
+
+ initialize()
+ for(var/obj/machinery/atmospherics/target in get_step(src,1))
+ if(target.initialize_directions & get_dir(target,src))
+ node1 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,2))
+ if(target.initialize_directions & get_dir(target,src))
+ node2 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,4))
+ if(target.initialize_directions & get_dir(target,src))
+ node3 = target
+ break
+
+ for(var/obj/machinery/atmospherics/target in get_step(src,8))
+ if(target.initialize_directions & get_dir(target,src))
+ node4 = target
+ break
+
+ var/turf/T = src.loc // hide if turf is not intact
+ hide(T.intact)
+ //update_icon()
+ update_icon()
+
+ manifold4w/scrubbers
+ name="Scrubbers pipe"
+ color="red"
+ icon_state = ""
+
+ manifold4w/supply
+ name="Air supply pipe"
+ color="blue"
+ icon_state = ""
+
+ manifold4w/supplymain
+ name="Main air supply pipe"
+ color="purple"
+ icon_state = ""
+
+ manifold4w/general
+ name="Air supply pipe"
+ color="gray"
+ icon_state = ""
+
+ manifold4w/scrubbers/visible
+ level = 2
+ icon_state = "manifold4w-r"
+
+ manifold4w/scrubbers/hidden
+ level = 1
+ icon_state = "manifold4w-r-f"
+
+ manifold4w/supply/visible
+ level = 2
+ icon_state = "manifold4w-b"
+
+ manifold4w/supply/hidden
+ level = 1
+ icon_state = "manifold4w-b-f"
+
+ manifold4w/supplymain/visible
+ level = 2
+ icon_state = "manifold4w-p"
+
+ manifold4w/supplymain/hidden
+ level = 1
+ icon_state = "manifold4w-p-f"
+
+ manifold4w/general/visible
+ level = 2
+ icon_state = "manifold4w"
+
+ manifold4w/general/hidden
+ level = 1
+ icon_state = "manifold4w-f"
+
obj/machinery/atmospherics/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
if (istype(src, /obj/machinery/atmospherics/pipe/tank))
return ..()
diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm
index be131922db8..a497091c9e3 100644
--- a/code/game/machinery/atmoalter/meter.dm
+++ b/code/game/machinery/atmoalter/meter.dm
@@ -71,15 +71,18 @@
usr << t
+/obj/machinery/meter/attack_ai(mob/user as mob)
+ return attack_hand(user)
+/obj/machinery/meter/attack_paw(mob/user as mob)
+ return attack_hand(user)
-/obj/machinery/meter/Click()
-
+/obj/machinery/meter/attack_hand(mob/user as mob)
if(stat & (NOPOWER|BROKEN))
return 1
var/t = null
- if (get_dist(usr, src) <= 3 || istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/dead))
+ if (get_dist(user, src) <= 3 || istype(user, /mob/living/silicon/ai) || istype(user, /mob/dead))
if (src.target)
var/datum/gas_mixture/environment = target.return_air()
if(environment)
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index f3190658e99..6c0bc8b1481 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -17,6 +17,8 @@ Buildable meters
#define PIPE_INSULATED_BENT 12
#define PIPE_GAS_FILTER 13
#define PIPE_GAS_MIXER 14
+#define PIPE_MTVALVE 15
+#define PIPE_MANIFOLD4W 16
/obj/item/pipe
name = "pipe"
@@ -65,6 +67,10 @@ Buildable meters
src.pipe_type = PIPE_GAS_MIXER
else if(istype(make_from, /obj/machinery/atmospherics/unary/vent_scrubber))
src.pipe_type = PIPE_SCRUBBER
+ else if(istype(make_from, /obj/machinery/atmospherics/tvalve))
+ src.pipe_type = PIPE_MTVALVE
+ else if(istype(make_from, /obj/machinery/atmospherics/pipe/manifold))
+ src.pipe_type = PIPE_MANIFOLD4W
else
src.pipe_type = pipe_type
src.dir = dir
@@ -92,6 +98,8 @@ Buildable meters
"bent insulated pipe", \
"gas filter", \
"gas mixer", \
+ "t-valve", \
+ "4-way manifold", \
)
name = nlist[pipe_type+1] + " fitting"
var/list/islist = list( \
@@ -110,6 +118,8 @@ Buildable meters
"insulated", \
"filter", \
"mixer", \
+ "mtvalve", \
+ "manifold4w", \
)
icon_state = islist[pipe_type + 1]
@@ -133,6 +143,8 @@ Buildable meters
dir = 1
else if(dir==8)
dir = 4
+ else if (pipe_type == PIPE_MANIFOLD4W)
+ dir = 2
//src.pipe_dir = get_pipe_dir()
return
@@ -168,11 +180,11 @@ Buildable meters
return dir|flip
if(PIPE_SIMPLE_BENT, PIPE_INSULATED_BENT, PIPE_HE_BENT)
return dir //dir|acw
- if(PIPE_CONNECTOR,PIPE_UVENT,PIPE_SCRUBBER)
+ if(PIPE_CONNECTOR,PIPE_UVENT,PIPE_SCRUBBER,PIPE_MANIFOLD4W)
return dir
if(PIPE_MANIFOLD)
return flip|cw|acw
- if(PIPE_GAS_FILTER, PIPE_GAS_MIXER)
+ if(PIPE_GAS_FILTER, PIPE_GAS_MIXER,PIPE_MTVALVE)
return dir|flip|cw
return 0
@@ -223,6 +235,8 @@ Buildable meters
dir = 1
else if(dir==8)
dir = 4
+ else if (pipe_type == PIPE_MANIFOLD4W)
+ dir = 2
var/pipe_dir = get_pipe_dir()
for(var/obj/machinery/atmospherics/M in src.loc)
@@ -308,6 +322,31 @@ Buildable meters
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
+ M.initialize_directions = pipe_dir
+ //M.New()
+ var/turf/T = M.loc
+ M.level = T.intact ? 2 : 1
+ M.initialize()
+ if (!M)
+ usr << "There's nothing to connect this manifold to! (with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
+ return 1
+ M.build_network()
+ if (M.node1)
+ M.node1.initialize()
+ M.node1.build_network()
+ if (M.node2)
+ M.node2.initialize()
+ M.node2.build_network()
+ if (M.node3)
+ M.node3.initialize()
+ M.node3.build_network()
+ if (M.node4)
+ M.node4.initialize()
+ M.node4.build_network()
+
if(PIPE_JUNCTION)
var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction/P = new ( src.loc )
P.dir = src.dir
@@ -450,6 +489,26 @@ Buildable meters
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
+ V.initialize_directions = pipe_dir
+ if (pipename)
+ V.name = pipename
+ var/turf/T = V.loc
+ V.level = T.intact ? 2 : 1
+ V.initialize()
+ V.build_network()
+ if (V.node1)
+ V.node1.initialize()
+ V.node1.build_network()
+ if (V.node2)
+ V.node2.initialize()
+ V.node2.build_network()
+ if (V.node3)
+ V.node3.initialize()
+ V.node3.build_network()
+
playsound(src.loc, 'Ratchet.ogg', 50, 1)
user.visible_message( \
"[user] fastens the [src].", \
@@ -501,3 +560,5 @@ Buildable meters
#undef PIPE_INSULATED_BENT
#undef PIPE_GAS_FILTER
#undef PIPE_GAS_MIXER
+#undef PIPE_MTVALVE
+#undef PIPE_MANIFOLD4W
diff --git a/code/game/machinery/pipe/pipe_dispenser.dm b/code/game/machinery/pipe/pipe_dispenser.dm
index 175ecc4c7ac..68ae5bd58f6 100644
--- a/code/game/machinery/pipe/pipe_dispenser.dm
+++ b/code/game/machinery/pipe/pipe_dispenser.dm
@@ -18,7 +18,9 @@
Pipe
Bent Pipe
Manifold
+4-Way Manifold
Manual Valve
+Manual T-Valve
Devices:
Connector
Unary Vent
diff --git a/icons/obj/atmospherics/digital_valve.dmi b/icons/obj/atmospherics/digital_valve.dmi
index 109af8e82a5..39a6d2bc43d 100644
Binary files a/icons/obj/atmospherics/digital_valve.dmi and b/icons/obj/atmospherics/digital_valve.dmi differ
diff --git a/icons/obj/atmospherics/pipe_manifold.dmi b/icons/obj/atmospherics/pipe_manifold.dmi
index a252c8ac8a8..f98f5869a44 100644
Binary files a/icons/obj/atmospherics/pipe_manifold.dmi and b/icons/obj/atmospherics/pipe_manifold.dmi differ
diff --git a/icons/obj/atmospherics/valve.dmi b/icons/obj/atmospherics/valve.dmi
index b29c3c16cc0..d0c85012933 100644
Binary files a/icons/obj/atmospherics/valve.dmi and b/icons/obj/atmospherics/valve.dmi differ
diff --git a/icons/obj/cigarettes.dmi b/icons/obj/cigarettes.dmi
index 67577df0722..634ce6957f1 100644
Binary files a/icons/obj/cigarettes.dmi and b/icons/obj/cigarettes.dmi differ
diff --git a/icons/obj/pipe-item.dmi b/icons/obj/pipe-item.dmi
index 459b7e52cc8..96cf274c7b8 100644
Binary files a/icons/obj/pipe-item.dmi and b/icons/obj/pipe-item.dmi differ