diff --git a/Code/!atoms.dm b/Code/!atoms.dm
index 994041f..b186002 100644
--- a/Code/!atoms.dm
+++ b/Code/!atoms.dm
@@ -15,6 +15,8 @@
#define FLOWFRAC 0.99 // fraction of gas transfered per process
+#define PRESSURELIMIT 4E9 // maximum pressure (temp*content) excess before a pipe segment takes pressure damage
+
//FLAGS BITMASK
#define ONBACK 1 // can be put in back slot
@@ -439,7 +441,7 @@
/obj
var/throwspeed = 0.0
var/throwing = null
- var/datum/module/mod
+ // var/datum/module/mod
/obj/mark
var/mark = ""
@@ -1898,16 +1900,6 @@ Total SMES charging rate should not exceed total power generation rate, or an ov
desc = "Sleeping Pills\nAdminister as required to calm person.\nCauses 10 minutes of drowsyness. MAY induce immediate sleep.\nWARNING: Neurodepressant! Do not overdose!\nWarning: Causes drowsiness!If drowsyness persists for over 15 minutes contact medical professional."
name = "Pill Canister- 'Sleeping Pills'"
-/obj/item/weapon/pipe
- name = "pipe"
- icon = 'pipe-item.dmi'
- icon_state = "straight"
- var/ptype = 0
- flags = TABLEPASS|DRIVABLE|FPRINT
- w_class = 4
- s_istate = "pipe"
- level = 2
-
/obj/item/weapon/prox_sensor
name = "Proximity Sensor"
icon_state = "motion0"
@@ -1953,6 +1945,7 @@ Total SMES charging rate should not exceed total power generation rate, or an ov
name = "Station Intercom (Radio)"
icon_state = "intercom"
anchored = 1.0
+ layer = 3.1
var/number = 0
/obj/item/weapon/radio/signaler
name = "Remote Signaling Device"
diff --git a/Code/Item/Weapon/pipe.dm b/Code/Item/Weapon/pipe.dm
new file mode 100644
index 0000000..f6fe55c
--- /dev/null
+++ b/Code/Item/Weapon/pipe.dm
@@ -0,0 +1,443 @@
+/*
+ * Pipe item
+ * used in constrction of pipe system; can be carried, moved, rotated, unlike static pipes
+ * can be laid on or underfloor; when welded, is added to the static pipe network
+ */
+
+
+obj/item/weapon/pipe
+ name = "pipe"
+ icon = 'pipe-item.dmi'
+ icon_state = "straight"
+ flags = TABLEPASS|DRIVABLE|FPRINT
+ w_class = 3
+ s_istate = "pipe"
+ level = 2
+ var/ptype = 0 // the type of pipe item:
+ // 0 1 2 3 4 5 6 7 8
+ //"pipe", "bent pipe", "h/e pipe", "bent h/e pipe", "connector", "manifold", "junction" vent inlet
+
+
+ // create a new pipe
+
+ New()
+ ..()
+
+ update()
+
+ //update the name and icon of the pipe item depending on the type
+
+ proc/update()
+ var/list/nlist = list("pipe", "bent pipe", "h/e pipe", "bent h/e pipe", "connector", "manifold", "junction", "vent", "inlet")
+ name = nlist[ptype+1] + " fitting"
+ updateicon()
+
+ //update the icon of the item
+
+ proc/updateicon()
+
+ var/list/islist = list("straight", "bend", "he-straight", "he-bend", "connector", "manifold", "junction", "vent", "inlet")
+
+ icon_state = islist[ptype + 1]
+
+ if(invisibility) // true if placed under floor
+ icon -= rgb(0,0,0,128) // fade the icon
+ else
+ icon = initial(icon) // otherwise reset to inital icon
+
+
+ // called to hide or unhide a pipe
+ // i=true if hiding
+
+ hide(var/i)
+
+ invisibility = i ? 101 : 0 // make hidden pipe items invisible
+ updateicon()
+
+
+ //called when a turf is attacked with a pipe item
+ // place the pipe on the turf, setting pipe level to 1 (underfloor) if the turf is not intact
+
+ proc/turf_place(turf/T, mob/user)
+
+ if(!isturf(user.loc))
+ return
+
+ if(get_dist(T,user) > 1)
+ user.client_mob() << "You can't lay pipe at a place that far away."
+ return
+
+ if(!T.intact && (ptype == 2 || ptype == 3 || ptype == 6) )
+ user.client_mob() << "That type of pipe cannot be laid under the floor."
+ return
+
+
+ user.drop_item() // drop the pipe at the user's feet
+ src.loc = T
+
+ level = 2 // defaults to above floor laying
+
+ if(!T.intact)
+ level = 1 // if floor is not intact, make a low-level pipe
+
+ anchored = 1 // anchor the item so that it can't be dragged around if placed
+ // otherwise able to drag underfloor pipes into intact turfs
+
+
+ // called when the item is dropped
+
+ dropped(mob/user)
+ src.anchored = 0 // set unanchored if dropped manually. Will be set anchored if placed (above)
+
+
+ // rotate the pipe item clockwise
+
+ verb/rotate()
+ set src in view(1)
+
+ if ( usr.stat || usr.restrained() )
+ return
+
+ var/turf/T = src.loc
+ if(isturf(T) && T.intact && level==1) // if the pipe is underfloor, don't rotate
+ return // incase the pipe has been revaled with a t-scanner
+
+ src.dir = turn(src.dir, -90)
+ return
+
+ // returns the p_dir from the pipe item type and dir
+
+ proc/get_pdir()
+
+ var/flip = turn(dir, 180)
+ var/cw = turn(dir, -90)
+ var/acw = turn(dir, 90)
+
+ switch(ptype)
+ if(0)
+ return dir|flip
+ if(1)
+ return dir|cw
+ if(2,3)
+ return 0
+ if(4,7,8)
+ return dir
+ if(5)
+ return dir|cw|acw
+ if(6)
+ return flip
+
+ return 0
+
+ // return the h_dir (heat-exchange pipes) from the type and the dir
+
+ proc/get_hdir()
+
+ var/flip = turn(dir, 180)
+ var/cw = turn(dir, -90)
+
+ switch(ptype)
+ if(0,1,4,5,7,8)
+ return 0
+ if(2)
+ return dir|flip
+ if(3)
+ return dir|cw
+ if(6)
+ return dir
+
+ return 0
+
+ /*
+ // test verb
+ // increment through the various pipe types
+
+ verb/inc()
+ set src in view(1)
+
+ ptype = (ptype+1)%9
+ update()
+ */
+
+ // attack with welding tool to lay the pipe
+
+ attackby(obj/item/weapon/W, mob/user)
+
+ var/turf/T = src.loc
+ if(!isturf(T)) // only do anything when located on a turf
+ return
+
+ if(T.intact && level==1) // if the pipe is underfloor and floor is in place, don't interact
+ return // in case the pipe has been revealed with a t-scanner
+
+ var/pipedir = src.get_pdir()|src.get_hdir() // all possible pipe dirs including h/e
+
+ if (istype(W, /obj/item/weapon/weldingtool) )
+ var/obj/item/weapon/weldingtool/WT = W
+ if (WT.welding && WT.weldfuel>=0)
+
+
+ for(var/obj/machinery/M in T) // check to make sure no other pipes conflit with this one
+
+ if(M.level == src.level) // only on same level
+ if( (M.p_dir & pipedir) || (M.h_dir & pipedir) ) // matches at least one direction on either type of pipe
+ user.client_mob() << "There is already a pipe at that location and position."
+ return
+
+ for(var/obj/brokenpipe/BP in T) // check for broken pipes
+ if(BP.level == src.level)
+ if(BP.p_dir & pipedir)
+ user.client_mob() << "The broken pipe needs to be removed first."
+ return
+
+ // no conflicts found
+ WT.weldfuel--
+
+ sleep(10)
+
+ // 0 1 2 3 4 5 6 7
+ //"pipe", "bent pipe", "h/e pipe", "bent h/e pipe", "connector", "manifold", "junction" vent
+
+ var/obj/machinery/pipes/P
+
+ switch(ptype)
+ if(0,1) // straight or bent pipe
+ P = new/obj/machinery/pipes(T)
+
+ P.icon_state = "[pipedir]"
+ P.level = level
+ P.update()
+ P.updateicon()
+
+ var/list/dirs = P.get_dirs()
+
+ P.node1 = get_machine(P.level, P.loc, dirs[1])
+ P.node2 = get_machine(P.level, P.loc, dirs[2])
+
+ if(2,3) // straight or bent h/e pipe
+ P = new/obj/machinery/pipes/heat_exch(T)
+ P.icon_state = "[pipedir]"
+ P.level = 2
+ P.update()
+ P.updateicon()
+
+ var/list/dirs = P.get_dirs()
+
+ P.node1 = get_he_machine(P.level, P.loc, dirs[1])
+ P.node2 = get_he_machine(P.level, P.loc, dirs[2])
+
+ if(4) // connector
+ var/obj/machinery/connector/C = new(T)
+ C.dir = src.dir
+ C.p_dir = src.dir
+ C.level = level
+
+ C.buildnodes()
+
+ setlineterm(C.node, C.vnode)
+
+
+ if(5) //manifold
+ var/obj/machinery/manifold/M = new(T)
+ M.dir = dir
+ M.p_dir = pipedir
+ M.level = level
+ M.buildnodes()
+ setlineterm(M.node1, M.vnode1)
+ setlineterm(M.node2, M.vnode2)
+ setlineterm(M.node3, M.vnode3)
+
+ if(6) //junctions
+ var/obj/machinery/junction/J = new(T)
+ J.dir = dir
+ J.p_dir = src.get_pdir()
+ J.h_dir = src.get_hdir()
+ J.level = 2
+
+ J.buildnodes()
+ setlineterm(J.node1, J.vnode1)
+ setlineterm(J.node2, J.vnode2)
+
+ if(7) // vent
+ var/obj/machinery/vent/V = new(T)
+ V.dir = src.dir
+ V.p_dir = src.dir
+ V.level = level
+
+ V.buildnodes()
+
+ setlineterm(V.node, V.vnode)
+
+ if(8) // inlet
+ var/obj/machinery/inlet/I = new(T)
+ I.dir = src.dir
+ I.p_dir = src.dir
+ I.level = level
+
+ I.buildnodes()
+
+ setlineterm(I.node, I.vnode)
+
+ // for pipe objects, now do updating of pipelines if needed
+ switch(ptype)
+ if(0,1,2,3) // new regular or or h/e pipe
+
+ // number of pipes connected to P
+ var/pipecon = (P.node1 && P.node1.ispipe()) + (P.node2 && P.node2.ispipe())
+
+ if(Debug) world << "Pipecon [pipecon]"
+
+ if(!pipecon) // simplest case - no connection pipes (but may be machines)
+ var/obj/machinery/pipeline/PL = new() // create a new pipeline
+ P.buildnodes(PL) // set new pipe to use new pl
+ PL.nodes += P // and add it
+ PL.numnodes = 1
+ PL.capmult = 2
+ plines += PL // and new pipeline to the global list
+ PL.setterm() // and ensure any connections to machines are made
+ PL.name = "pipeline #[plines.Find(PL)]" // set the name
+
+ else if(pipecon == 1) // single connected pipe
+
+ var/obj/machinery/pipes/CP // the connected pipe
+
+ if(P.node1 && P.node1.ispipe()) // find the connected pipe
+ CP = P.node1
+ else
+ CP = P.node2
+
+ var/obj/machinery/pipeline/PL = CP.pl // the pipeline we connected to
+
+ P.buildnodes(PL) // set the pipeline and nodes of any adjoining pipes
+
+ if(PL.nodes[1] == CP) // if the connected pipe is at start of line nodes list
+ PL.nodes.Insert(1, P) // insert new pipe into start of node list
+ else
+ PL.nodes += P // otherwise, insert it at end
+ PL.numnodes++
+ PL.capmult++
+ PL.setterm() // connect to any machines
+
+ CP.termination = 0 // connected pipe no longer terminal
+
+ else //(pipecon==2)
+
+ var/obj/machinery/pipes/CP1 = P.node1
+ var/obj/machinery/pipes/CP2 = P.node2
+
+ var/obj/machinery/pipeline/PL1 = CP1.pl
+ var/obj/machinery/pipeline/PL2 = CP2.pl
+
+ if(PL1 == PL2) // special case - completing a loop
+ // make sure to check if this works properly
+ P.buildnodes(PL1)
+
+ PL1.nodes += P
+ PL1.numnodes++
+ PL1.capmult++
+ PL1.setterm()
+
+ CP1.termination = 0
+ CP2.termination = 0
+
+ PL1.vnode1 = PL1 // link pipeline to self
+ PL1.vnode2 = PL1
+
+ else // separate pipelines
+
+ P.buildnodes(PL1)
+
+ CP1.termination = 0
+ CP2.termination = 0
+
+ var/list/plist
+ if(PL1.nodes[1] == CP1)
+ plist = pipelist(null, PL1.nodes[PL1.nodes.len])
+ else
+ plist = pipelist(null, PL1.nodes[1])
+
+ PL1.gas.transfer_from(PL2.gas, -1)
+ PL1.ngas.transfer_from(PL2.ngas, -1)
+
+ plines -= PL2
+ for(var/obj/machinery/pipes/OP in PL2.nodes)
+ OP.pl = PL1
+
+ PL1.nodes = plist
+ PL1.numnodes = plist.len
+ PL1.capmult = plist.len+1
+
+
+ PL1.setterm()
+
+ del(PL2)
+
+
+
+ del(src) // remove the pipe item
+
+ return
+
+
+ // ensure that setterm() is called for a newly connected pipeline
+
+ proc/setlineterm(var/obj/machinery/node, var/obj/machinery/vnode)
+
+ if(vnode)
+ if( istype(vnode, /obj/machinery/pipeline) )
+
+
+ var/obj/machinery/pipeline/PL = vnode
+ node.buildnodes(PL)
+ PL.setterm()
+ else
+ node.buildnodes()
+
+
+ // set the type and orientation of a pipe fitting to the same as the pipe object it is being created from
+
+ proc/settype(var/obj/machinery/M)
+
+ if(istype(M, /obj/machinery/pipes)) // is a type of pipe
+
+ ptype = 0 // the base pipe type
+ var/pipedir = M.p_dir
+ if(istype(M, /obj/machinery/pipes/heat_exch)) //if a h/e pipe
+ pipedir = M.h_dir // pipedirs form h_dir
+ ptype = 2 // base pipetype is 2
+
+ switch(pipedir) // find the pipe orientation and type from the pipe dirs
+ if(3) // straight N-S
+ dir = SOUTH
+ if(12) // straight E-W
+ dir = EAST
+ if(5) // bent N-E
+ dir = NORTH
+ ptype++
+ if(6) // bent E-S
+ dir = EAST
+ ptype++
+ if(10) // bent S-W
+ dir = SOUTH
+ ptype++
+ if(9) // bent W-N
+ dir = WEST
+ ptype++
+ else if(istype(M, /obj/machinery/connector))
+ ptype = 4
+ dir = M.dir
+ else if(istype(M, /obj/machinery/manifold))
+ ptype = 5
+ dir = M.dir
+ else if(istype(M, /obj/machinery/junction))
+ ptype = 6
+ dir = M.h_dir // junction h/e pipe is always in object direction
+ else if(istype(M, /obj/machinery/vent))
+ ptype = 7
+ dir = M.dir
+ else if(istype(M, /obj/machinery/inlet))
+ ptype = 8
+ dir = M.dir
+
+
+ update()
diff --git a/Code/Machinery/Power/apc.dm b/Code/Machinery/Power/apc.dm
index 6c1d662..5d42b97 100644
--- a/Code/Machinery/Power/apc.dm
+++ b/Code/Machinery/Power/apc.dm
@@ -29,6 +29,8 @@ obj/machinery/power/apc
anchored = 1
netnum = -1 // Always -1, set so that APCs aren't found as powernet nodes
// instead, all connections are done through the associated terminal object
+ layer = 3.1 // slightly above standard obj layer
+
var
area/area // the area that this APC controls
obj/item/weapon/cell/cell // the power cell object inserted in this APC (or null if none)
diff --git a/Code/Machinery/Power/solar_control.dm b/Code/Machinery/Power/solar_control.dm
index a31434c..0e6e9ad 100644
--- a/Code/Machinery/Power/solar_control.dm
+++ b/Code/Machinery/Power/solar_control.dm
@@ -55,7 +55,7 @@ obj/machinery/power/solar_control
icon_state = "solar_con"
overlays = null
if(cdir > 0)
- overlays += image('enginecomputer.dmi', "solcon-o", FLY_LAYER, cdir)
+ overlays += image('enginecomputer.dmi', "solcon-o[cdir]", FLY_LAYER)
// Attack by AI, open interaction window
@@ -168,7 +168,7 @@ obj/machinery/power/solar_control
if (usr.stat || usr.restrained() )
return
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
- if (!istype(usr, /mob/ai))
+ if (!istype(usr, /mob/ai))
if (!istype(usr, /mob/drone))
usr.client_mob() << "\red You don't have the dexterity to do this!"
return
diff --git a/Code/Machinery/_machinery.dm b/Code/Machinery/_machinery.dm
index bcea21d..14eab61 100644
--- a/Code/Machinery/_machinery.dm
+++ b/Code/Machinery/_machinery.dm
@@ -18,7 +18,7 @@ obj/machinery
capmult = 0 // used for gas flow - a capacity multiplier
stat = 0 // machinery status bitflags
- // currently used values: 1 - BROKEN ; 2 - NOPOWER
+ // currently used values: 1 - BROKEN ; 2 - NOPOWER ; 8 - MAINT
// New() and Del() add and remove machines from the global "machines" list
diff --git a/Code/Machinery/_pipe_misc.dm b/Code/Machinery/_pipe_misc.dm
index b762f3f..452342b 100644
--- a/Code/Machinery/_pipe_misc.dm
+++ b/Code/Machinery/_pipe_misc.dm
@@ -91,6 +91,10 @@
for(var/obj/machinery/M in T.contents)
if(M.level == level)
if(M.p_dir & flip)
+ var/obj/machinery/pipes/P = M
+ if(istype(P))
+ if (P.stat & BROKEN)
+ continue
return M
return null
@@ -108,6 +112,10 @@
for(var/obj/machinery/M in T.contents)
if(M.level == level)
if(M.h_dir & flip)
+ var/obj/machinery/pipes/P = M
+ if(istype(P))
+ if (P.stat & BROKEN)
+ continue
return M
return null
@@ -164,4 +172,32 @@
sngas.turf_take(T, delta_gt) // grab gas from turf and direcly add it to the new gas
- T.res_vars() // update turf gas vars for both cases
\ No newline at end of file
+ T.res_vars() // update turf gas vars for both cases
+
+
+
+// Called by all pipe-related objects (except pipes themselves) when attack with a weldingtool
+// Create the relevant pipe fitting item from the pipe object
+// Returns true if succeeded, false otherwise
+
+/obj/machinery/proc/attack_welder(obj/item/weapon/weldingtool/WT, mob/user)
+
+ if(WT.welding)
+ if(WT.weldfuel > 3)
+ WT.weldfuel -=3
+
+ user << "\blue Removing the [name]. Stand still as this takes some time."
+ var/turf/T = user.loc
+ sleep(50)
+
+ if ((user.loc == T && user.equipped() == WT))
+ // make pipe fitting
+
+ var/obj/item/weapon/pipe/P = new(src.loc)
+ P.settype(src)
+
+ return 1
+ else
+ user << "\blue You need more welding fuel to remove the [name]."
+
+ return 0
\ No newline at end of file
diff --git a/Code/Machinery/alarm.dm b/Code/Machinery/alarm.dm
index 360a2c8..e5d372a 100644
--- a/Code/Machinery/alarm.dm
+++ b/Code/Machinery/alarm.dm
@@ -8,7 +8,7 @@ obj/machinery/alarm
icon = 'stationobjs.dmi'
icon_state = "alarm:0"
anchored = 1.0
-
+ layer = 3.1
// Monitors location air quality and changes icon_state to reflect it
diff --git a/Code/Machinery/autolathe.dm b/Code/Machinery/autolathe.dm
index 741799a..f58a2cd 100644
--- a/Code/Machinery/autolathe.dm
+++ b/Code/Machinery/autolathe.dm
@@ -59,7 +59,7 @@ obj/machinery/autolathe
attack_ai(mob/user)
return src.attack_hand(user)
-
+
// Open interaction window
// Currenty only pipe pieces can be made
attack_hand(mob/user)
@@ -82,6 +82,7 @@ obj/machinery/autolathe
L["manif"] = "Pipe manifold (15000 cc)"
L["junct"] = "Pipe junction (10000 cc)"
L["vent"] = "Pipe vent (10000 cc)"
+ L["inlet"] = "Pipe inlet (10000 cc)"
if (config.enable_drones)
L["drone"] = "Robot drone (150,000 cc)"
/* L["screwdriver"] = "Make Screwdriver {40 cc}"
@@ -135,6 +136,7 @@ obj/machinery/autolathe
C["manif"] = 15000
C["junct"] = 10000
C["vent"] = 10000
+ C["inlet"] = 10000
if (config.enable_drones)
C["drone"] = 150000
@@ -161,6 +163,8 @@ obj/machinery/autolathe
new /obj/item/weapon/pipe{ ptype = 6 }(src.loc)
if("vent")
new /obj/item/weapon/pipe{ ptype = 7 }(src.loc)
+ if("inlet")
+ new /obj/item/weapon/pipe{ ptype = 8 }(src.loc)
if("drone")
if (config.enable_drones)
var/mob/drone/drone = new /mob/drone(src.loc)
diff --git a/Code/Machinery/circulator.dm b/Code/Machinery/circulator.dm
index a625dad..4cf8c8d 100644
--- a/Code/Machinery/circulator.dm
+++ b/Code/Machinery/circulator.dm
@@ -62,25 +62,21 @@ obj/machinery/circulator
buildnodes()
- var/turf/TS = get_step(src, SOUTH)
- var/turf/TN = get_step(src, NORTH)
+ var/turf/T = src.loc
- for(var/obj/machinery/M in TS)
-
- if(M && (M.p_dir & 1))
- node1 = M
- break
-
- for(var/obj/machinery/M in TN)
-
- if(M && (M.p_dir & 2))
- node2 = M
- break
+ node1 = get_machine(level, T, SOUTH)
+ node2 = get_machine(level, T, NORTH)
- if(node1) vnode1 = node1.getline()
+ if(node1)
+ vnode1 = node1.getline()
+ else
+ vnode1 = null
- if(node2) vnode2 = node2.getline()
+ if(node2)
+ vnode2 = node2.getline()
+ else
+ vnode2 = null
// Set the current status and pumping rate (as a percentage)
diff --git a/Code/Machinery/connector.dm b/Code/Machinery/connector.dm
index 1b3d06e..81e4277 100644
--- a/Code/Machinery/connector.dm
+++ b/Code/Machinery/connector.dm
@@ -53,15 +53,12 @@
buildnodes()
- var/turf/T = get_step(src.loc, src.dir)
- var/fdir = turn(src.p_dir, 180)
+ node = get_machine(level, src.loc, dir)
- for(var/obj/machinery/M in T)
- if(M.p_dir & fdir)
- src.node = M
- break
-
- if(node) vnode = node.getline()
+ if(node)
+ vnode = node.getline()
+ else
+ vnode = null
return
@@ -135,3 +132,16 @@
if(T && !T.density)
flow_to_turf(gas, ngas, T)
+
+ // Attack by item
+ // If welder, make a fitting and delete self
+
+ attackby(obj/item/weapon/W, mob/user)
+
+ if(istype(W, /obj/item/weapon/weldingtool))
+ if(attack_welder(W, user))
+ if(connected)
+ connected.anchored = 0 // if connected equipment, unanchor it before deleting the connector
+ del(src)
+ else
+ ..()
diff --git a/Code/Machinery/cryocell.dm b/Code/Machinery/cryocell.dm
index bc1aa64..8ae66e5 100644
--- a/Code/Machinery/cryocell.dm
+++ b/Code/Machinery/cryocell.dm
@@ -65,7 +65,10 @@ obj/machinery/cryo_cell
line_in = get_machine(level, T, p_dir )
- if(line_in) vnode = line_in.getline()
+ if(line_in)
+ vnode = line_in.getline()
+ else
+ vnode = null
@@ -203,7 +206,7 @@ obj/machinery/cryo_cell
if (stat & NOPOWER) return
if ((!( istype(G, /obj/item/weapon/grab) ) || !( ismob(G.affecting) )))
- return
+ return
var/result = src.canReach(user, null, 1)
if (result==0)
user.client_mob() << "You can't reach [src]."
@@ -473,4 +476,4 @@ obj/machinery/cryo_cell
allow_drop()
return 0
- */
+ */
diff --git a/Code/Machinery/firealarm.dm b/Code/Machinery/firealarm.dm
index c5cc3eb..e182cb1 100644
--- a/Code/Machinery/firealarm.dm
+++ b/Code/Machinery/firealarm.dm
@@ -9,6 +9,7 @@ obj/machinery/firealarm
icon = 'items.dmi'
icon_state = "firealarm"
anchored = 1
+ layer = 3.1 // slightly above standard obj layer
var
detecting = 1 // true if the alarm is working, false if disabled
//working = 1 // unused
diff --git a/Code/Machinery/freezer.dm b/Code/Machinery/freezer.dm
index 762a0a2..422f2bc 100644
--- a/Code/Machinery/freezer.dm
+++ b/Code/Machinery/freezer.dm
@@ -61,7 +61,10 @@ obj/machinery/freezer
line_out = get_machine(level, T, p_dir )
- if(line_out) vnode = line_out.getline() // the pipeline associated with the pipe
+ if(line_out)
+ vnode = line_out.getline() // the pipeline associated with the pipe
+ else
+ vnode = null
// Update gas levels with the new levels calculated in process()
@@ -99,7 +102,7 @@ obj/machinery/freezer
attack_paw(mob/user)
return src.attack_hand(user)
-
+
// AI interact
attack_ai(mob/user)
return src.attack_hand(user)
@@ -175,11 +178,11 @@ obj/machinery/freezer
Topic(href, href_list)
..()
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
- if (!istype(usr, /mob/ai))
+ if (!istype(usr, /mob/ai))
usr.client_mob() << "\red You don't have the dexterity to do this!"
return
if ((usr.stat || usr.restrained()))
- if (!istype(usr, /mob/ai))
+ if (!istype(usr, /mob/ai))
return
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
usr.machine = src
diff --git a/Code/Machinery/inlet.dm b/Code/Machinery/inlet.dm
index 432df9c..a0da025 100644
--- a/Code/Machinery/inlet.dm
+++ b/Code/Machinery/inlet.dm
@@ -42,15 +42,12 @@ obj/machinery/inlet
buildnodes()
- var/turf/T = get_step(src.loc, src.dir)
- var/fdir = turn(src.p_dir, 180)
+ node = get_machine(level, src.loc, dir)
- for(var/obj/machinery/M in T)
- if(M.p_dir & fdir)
- src.node = M
- break
-
- if(node) vnode = node.getline()
+ if(node)
+ vnode = node.getline()
+ else
+ vnode = null
return
@@ -101,6 +98,18 @@ obj/machinery/inlet
flow_to_turf(gas, ngas, T)
+ // Attack by item
+ // If welder, make a fitting and delete self
+
+ attackby(obj/item/weapon/W, mob/user)
+
+ if(istype(W, /obj/item/weapon/weldingtool))
+ if(attack_welder(W, user))
+ del(src)
+ else
+ ..()
+
+
//Filtration Procs for Filtered Inlet
/obj/machinery/proc
@@ -328,19 +337,17 @@ obj/machinery/inletfiltered
buildnodes()
- var/turf/T = get_step(src.loc, src.dir)
- var/fdir = turn(src.p_dir, 180)
+ node = get_machine(level, src.loc, dir)
- for(var/obj/machinery/M in T)
- if(M.p_dir & fdir)
- src.node = M
- break
-
- if(node) vnode = node.getline()
+ if(node)
+ vnode = node.getline()
+ else
+ vnode = null
return
+
// Returns the gas fullness value. Capmult is 2 for inlets because they in effect have two connections: the pipe, and the turf
get_gas_val(from)
diff --git a/Code/Machinery/junction.dm b/Code/Machinery/junction.dm
index 5fa13a0..fa39294 100644
--- a/Code/Machinery/junction.dm
+++ b/Code/Machinery/junction.dm
@@ -5,7 +5,7 @@
obj/machinery/junction
name = "junction"
- icon = 'junct-pipe.dmi'
+ icon = 'pipes.dmi'
icon_state = "junction"
desc = "A junction between regular and heat-exchanger pipework."
anchored = 1
@@ -49,8 +49,8 @@ obj/machinery/junction
node2 = get_machine(level, T , p_dir ) // the regular pipe
- if(node1) vnode1 = node1.getline()
- if(node2) vnode2 = node2.getline()
+ vnode1 = node1 ? node1.getline() : null
+ vnode2 = node2 ? node2.getline() : null
return
@@ -111,3 +111,13 @@ obj/machinery/junction
flow_to_turf(gas, ngas, T)
+ // Attack by item
+ // If welder, make a fitting and delete self
+
+ attackby(obj/item/weapon/W, mob/user)
+
+ if(istype(W, /obj/item/weapon/weldingtool))
+ if(attack_welder(W, user))
+ del(src)
+ else
+ ..()
diff --git a/Code/Machinery/light_switch.dm b/Code/Machinery/light_switch.dm
index 1bcd199..57ee1f5 100644
--- a/Code/Machinery/light_switch.dm
+++ b/Code/Machinery/light_switch.dm
@@ -11,6 +11,7 @@ obj/machinery/light_switch
icon = 'power.dmi'
icon_state = "light1"
anchored = 1.0
+ layer = 3.1
var
on = 1 // true if currently switched on
area/area = null // holds the area object that this switch controls
diff --git a/Code/Machinery/manifold.dm b/Code/Machinery/manifold.dm
index eddf200..c09915a 100644
--- a/Code/Machinery/manifold.dm
+++ b/Code/Machinery/manifold.dm
@@ -74,9 +74,9 @@ obj/machinery/manifold
node2 = get_machine( level, T , n2dir )
- if(node1) vnode1 = node1.getline()
- if(node2) vnode2 = node2.getline()
- if(node3) vnode3 = node3.getline()
+ vnode1 = node1 ? node1.getline() : null
+ vnode2 = node2 ? node2.getline() : null
+ vnode3 = node3 ? node3.getline() : null
return
@@ -146,3 +146,13 @@ obj/machinery/manifold
+ // Attack by item
+ // If welder, make a fitting and delete self
+
+ attackby(obj/item/weapon/W, mob/user)
+
+ if(istype(W, /obj/item/weapon/weldingtool))
+ if(attack_welder(W, user))
+ del(src)
+ else
+ ..()
diff --git a/Code/Machinery/meter.dm b/Code/Machinery/meter.dm
index 7285249..533dd68 100644
--- a/Code/Machinery/meter.dm
+++ b/Code/Machinery/meter.dm
@@ -3,6 +3,7 @@
*
* The meter actually reads a moving average of the flow var of the pipeline object associated with the pipe.
* Note that the value can be negative if the flow is going through the pipe "backwards"
+ * If attacked by a wrench, try to locate a working pipe again
*
* TODO: Add an icon overlay showing the actual movement direction of the gas.
*/
@@ -15,6 +16,7 @@ obj/machinery/meter
var
obj/machinery/pipes/target = null // the pipe object to monitor
average = 0 // the exponential moving average of the flow rate
+ alarm = 0 // true if pressure alarm is being shown
@@ -34,20 +36,32 @@ obj/machinery/meter
process()
- if(!target)
+ if(!target || !target.pl)
icon_state = "meterX"
+ overlays = null
return
if(stat & NOPOWER)
icon_state = "meter0"
return
+ var/obj/machinery/pipeline/line = target.pl
use_power(5)
- average = 0.5 * average + 0.5 * target.pl.flow
+ average = 0.5 * average + 0.5 * line.flow
var/val = min(18, round( 18.99 * ((abs(average) / 2500000)**0.25)) )
icon_state = "meter[val]"
+ var/pressure = line.gas.tot_gas() / line.numnodes * line.gas.temperature
+
+ if(alarm)
+ if(pressure < PRESSURELIMIT)
+ overlays = null
+ alarm = 0
+ else
+ if(pressure > PRESSURELIMIT)
+ overlays += image('pipes.dmi', "meter-o")
+ alarm = 1
// If the meter is clicked on, report the flow rate and temperature of the gas
@@ -55,16 +69,38 @@ obj/machinery/meter
var/mob/user = usr
if (user.currentDrone!=null)
user = user.currentDrone
-
+
if (get_dist(user, src) <= 3)
if (src.target)
- user.client_mob() << text("\blue Results:\nMass flow []%\nTemperature [] K", round(100*abs(average)/6e6, 0.1), round(target.pl.gas.temperature,0.1))
+ user.client_mob() << "\blue Results:\nMass flow [round(100*abs(average)/6e6, 0.1)]%\nTemperature [round(target.pl.gas.temperature,0.1)] K"
+ if(alarm)
+ user.client_mob() << "\red Warning! Pressure approaching pipe fracture limit!"
else
user.client_mob() << "\blue Results: Connection Error!"
else
user.client_mob() << "\blue You are too far away."
return
+
+ // Attack with weapon
+ // if a wrench, try to find pipe at same location and activate
+
+ attackby(var/obj/item/weapon/W, mob/user)
+
+ if(!target && istype(W, /obj/item/weapon/wrench))
+ target = locate(/obj/machinery/pipes, src.loc)
+ average = 0
+ if(target)
+ user.client_mob() << "\blue The meter has been attached to the pipe."
+ var/turf/T = src.loc // make sure meter is on top of pipe
+ src.loc = null
+ src.loc = T
+ else
+ ..()
+
+
+
+
// Disabled routines
/*
diff --git a/Code/Machinery/pipeline.dm b/Code/Machinery/pipeline.dm
index 0184228..b59daef 100644
--- a/Code/Machinery/pipeline.dm
+++ b/Code/Machinery/pipeline.dm
@@ -44,6 +44,16 @@ obj/machinery/pipeline // logical pipeline consisting of multiple /obj/machin
gasflowlist += src
+ // Delete a pipeline, remove from gasflowlist and pipeline list
+
+ Del()
+ gasflowlist -= src
+ plines -= src
+ ..()
+
+
+
+
// Sets the vnode1 & vnode2 values to the machines connected at each end of the pipe
// Also orientates the pipes in the node list so that for each pipe, node1 points to previous entry, and node2 points to next
@@ -109,7 +119,8 @@ obj/machinery/pipeline // logical pipeline consisting of multiple /obj/machin
// Timed process for the pipeline.
// First do heat-exchange for every node in this pipeline
- // The do standard gas flow from each end of the pipeline.
+ // Also check for overpressure condition
+ // Then do standard gas flow from each end of the pipeline.
// Also update "flow" variable to show rate of flow through the complete pipeline.
process()
@@ -128,6 +139,16 @@ obj/machinery/pipeline // logical pipeline consisting of multiple /obj/machin
P.heat_exchange(ngas, tot_node, numnodes, gtemp) // exchange heat with its turf
+ // check for pressure breakage
+ if( tot_node * gtemp > PRESSURELIMIT)
+ var/obj/machinery/pipes/P = pick(nodes) // pick a random pipe segment to damage
+ var/turf/PT = P.loc
+
+ if( (tot_node * gtemp - PT.pressure()) > PRESSURELIMIT )
+ P.health--
+ P.healthcheck()
+
+
// now do standard gas flow proc
var/delta_gt
diff --git a/Code/Machinery/pipes.dm b/Code/Machinery/pipes.dm
index a032ea7..861da97 100644
--- a/Code/Machinery/pipes.dm
+++ b/Code/Machinery/pipes.dm
@@ -4,16 +4,17 @@
* Pipes do not directly contain gas, but unbroken chains of pipes are assembled into /obj/machinery/pipeline objects
* Pipelines contain a single gas reservoir that encompass all the gas that would be each individual pipe.
*
- * TODO: Complete routines for pipe disassembly, damage, and exploding under pressure.
- * TODO: Finalize method of showing broken pipes & pipe ends.
* TODO: Implement some method of capacity regulation
*/
+#define MAXPIPEHEALTH 10 // the starting health value of each pipe
+
obj/machinery/pipes
name = "pipes"
icon = 'reg_pipe.dmi'
icon_state = "12"
anchored = 1
+ desc = "A regular pipe."
/* var/p_dir - inherited from /obj/machinery, is a bitfield of directions of pipe connections from this one */
@@ -25,7 +26,7 @@ obj/machinery/pipes
insulation = NORMPIPERATE // lower insulation value means pipe temperature is exchanged with turf at a faster rate
obj/machinery/pipeline/pl // the pipeline object which contains this pipe
- health = 10 // the health of the pipe (not yet implemented)
+ health = MAXPIPEHEALTH // the health of the pipe
// Create a new pipe, and update the p_dir according to the icon_state.
@@ -62,6 +63,9 @@ obj/machinery/pipes
node1 = get_machine(level, src.loc, dirs[1])
node2 = get_machine(level, src.loc, dirs[2])
+ if(!line) // If no pipeline was specified, just needed to revalidate the local nodes
+ return
+
if(pl) // If the pipeline is already set, there is no need to propagate anymore
return
@@ -162,6 +166,30 @@ obj/machinery/pipes
return list(dirs[2], dirs[1]) // otherwise swap order
+ // examine verb - show description and amount of damage
+
+ examine()
+ set src in view(1)
+ if(usr && !usr.stat)
+ usr.client_mob() << "[desc] The pipe is [damagetext()][(stat & MAINT)?" and the flanges are unfastened.":"."]"
+
+
+ // return text description of the damage state of the pipe
+ // used in examine verb and when repairing
+
+ proc/damagetext()
+ if(health == MAXPIPEHEALTH)
+ return "undamaged"
+ if(health > 0.7*MAXPIPEHEALTH)
+ return "slightly damaged"
+ if(health > 0.3*MAXPIPEHEALTH)
+ return "damaged"
+ else
+ return "badly damaged"
+
+
+
+
// Update the icon_state and overlays
// Depends on pipe level and visibility, broken status, and whether this is an unterminated end of a pipe
@@ -171,9 +199,6 @@ obj/machinery/pipes
var/is = "[p_dir]"
- if(stat & BROKEN)
- is += "-b"
-
// Set invisibility status depending on whether this pipe is below floor level
// Also sets a faded (alpha blended) icon_state for the pipe so it can be shown with a T-scanner
@@ -187,20 +212,21 @@ obj/machinery/pipes
src.icon_state = is
// If either node is null, this is an unterminated pipe
+ // unless a matching broken pipe is present
// Show special overlays to indicate this
var/list/dirs = get_node_dirs()
overlays = null
- if(!node1 && !node2) // neither end of pipe is connected
- overlays += image('pipes.dmi', "discon", FLY_LAYER, dirs[1])
- overlays += image('pipes.dmi', "discon", FLY_LAYER, dirs[2])
- else if(!node1) // node1 is not connected
- overlays += image('pipes.dmi', "discon", FLY_LAYER, dirs[1])
+ if(!node1) // node1 is not connected
+ if(!findbrokenpipe(T, dirs[1], level, 0)) // no broken pipe present
+ overlays += image('pipes.dmi', "discon[dirs[1]]", FLY_LAYER)
else if(!node2) // node2 is not connected
- overlays += image('pipes.dmi', "discon", FLY_LAYER, dirs[2])
+ if(!findbrokenpipe(T, dirs[2], level, 0)) // no broken pipe present
+ overlays += image('pipes.dmi', "discon[dirs[2]]", FLY_LAYER)
+
return
@@ -243,38 +269,258 @@ obj/machinery/pipes
// Routines to allow cutting and damage of pipes
- // Not yet implemented
- /*
attackby(obj/item/weapon/W, mob/user)
- if (istype(W, /obj/item/weapon/weldingtool))
+ if (istype(W, /obj/item/weapon/wrench))
+ if(stat & MAINT)
+ stat &= ~MAINT
+ user.client_mob() << "\blue You fasten the pipe flanges."
+ else
+ stat |= MAINT
+ user.client_mob() << "\blue You unfasten the pipe flanges. The pipe can now be cut."
+
+ else if (istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
- if(WT.welding && WT.weldfuel > 3)
- WT.weldfuel -=3
+ if(WT.welding)
- user.client_mob() << "\blue Cutting the pipe. Stand still as this takes some time."
- var/turf/T = user.loc
- sleep(50)
+ if(stat & MAINT)
+ if(WT.weldfuel > 3)
+ WT.weldfuel -=3
- if ((user.loc == T && user.equipped() == W))
+ user.client_mob() << "\blue Cutting the pipe. Stand still as this takes some time."
+ var/turf/T = user.loc
+ sleep(50)
+
+ if ((user.loc == T && user.equipped() == W))
+ // make pipe fitting
+
+ var/obj/item/weapon/pipe/P = new(src.loc)
+ P.settype(src)
+
+ del(src)
+ else
+ user.client_mob() << "\blue You need more welding fuel to cut the pipe."
+
+ else
+ if(health < MAXPIPEHEALTH)
+ if(WT.weldfuel > 1)
+ WT.weldfuel--
+
+ user.client_mob() << "\blue Repairing the pipe."
+ sleep(5)
+ health = min(health+MAXPIPEHEALTH/10, MAXPIPEHEALTH)
+ user.client_mob() << "\blue The pipe is now [damagetext()]."
+ healthcheck()
+ return
+ else
+ user.client_mob() << "\blue You need more welding fuel to repair the pipe."
+
+ else
+ user.client_mob() << "You cannot repair the pipe as it is undamaged."
+ return
- // make pipe fitting
- sleep(1)
else
- var/aforce = W.force
+ var/aforce = round(W.force/10+0.5,1)
src.health = max(0, src.health - aforce)
healthcheck()
-
+ ..()
return
- proc/healthcheck()
- //if(health<1)
+
+
+ // pipe effected by an explosion
+
+ ex_act(severity)
+
+ switch(severity)
+ if(1.0)
+ del(src)
+ return
+ if(2.0)
+ health -= rand(MAXPIPEHEALTH*0.5,MAXPIPEHEALTH*1.5)
+ healthcheck()
+ return
+ if(3.0)
+ health -= rand(0,MAXPIPEHEALTH*1.5)
+ healthcheck()
+ return
+
+
+ // pipe is in a fire
+
+
+ burn(fi_amount)
+
+ if(fi_amount > 1800000)
+ var/turf/T = src.loc
+ if(prob(5) && T.temp > 1600) // if turf temp exceeds pipe melting point, take damage
+ health -= round( T.temp/1500) // damage depends on the actual temperature
+ healthcheck()
+
+
+ /*
+ // test verb - destroy a pipe
+
+ verb/destroy()
+ set src in view()
+
+ health=0
+ healthcheck()
*/
+ // Check the pipe hp, and break it if low enough
+
+ proc/healthcheck()
+ if(health<=0) // check health, if low enough
+ health = 0 // break the pipe
+ breakpipe()
+
+
+ // break a pipe
+ // create a broken pipe object in place, then delete this pipe
+ // pipe Del() proc handles updating of the containing pipeline
+
+ proc/breakpipe()
+
+ if(!isturf(src.loc)) // sanity check
+ return
+
+ // create the broken pipe object
+
+ var/obj/brokenpipe/BP = new(src.loc) // in same loc as original
+ BP.update(src) // update brokenpipe vars from this pipe
+
+ // deletes the pipe segement
+ del(src)
+
+
+ // Delete the pipe
+ // must handle updating of the containing pipeline object
+ // three possible cases:
+ // pipe is the only node in a line -> delete the line
+ // pipe is at one end of a line -> shorten the line
+ // pipe is in the middle of a line -> split the line into two pieces
+ // also handle redistribution of gas in the pipeline(s)
+
+ Del()
+
+ var/obj/machinery/pipeline/line = pl
+ var/turf/T = src.loc
+
+ if(!pl || !isturf(T)) // sanity check
+ return ..() // just delete
+
+ var/linepos = line.nodes.Find(src) // the position of this pipe in the pipeline
+
+ if(linepos == 1 && line.numnodes == 1) // single pipe pipeline
+ // no other nodes in the pipeline, so remove it completely
+ line.gas.leak(T) // dump all gas in line into turf
+ src.pl = null
+
+
+ // update linked machines to reflect new status
+ if(line.vnode1)
+ line.vnode1.buildnodes()
+
+ if(line.vnode2)
+ line.vnode2.buildnodes()
+
+ line.nodes -= src // remove reference to this pipe object (to prevent infinite loop)
+ del(line) // remove the line
+
+ else if(linepos == 1 || linepos == line.numnodes) // pipe was at one end of pipeline
+
+ var/obj/substance/gas/G = new() // temporary holder for gas
+
+ G.transfer_from(line.gas, line.gas.tot_gas() / line.numnodes) // transfer gas from line to temp
+
+ G.leak(T) // dump fraction of line gas into turf
+
+
+ line.nodes -= src
+ line.numnodes--
+ line.capmult = 1 + line.numnodes
+
+ src.loc = null
+
+ line.ngas.replace_by(line.gas)
+
+ // now update line and connected machines links between nodes
+
+ if(linepos == 1) // pipe at start of pipeline
+ if(line.vnode1) line.vnode1.buildnodes()
+ var/obj/machinery/pipes/P = line.nodes[1]
+
+ P.buildnodes(null) // rebuild the local nodes of the next pipe
+ line.vnode1 = null
+ else // pipe at end of pipeline
+ if(line.vnode2) line.vnode2.buildnodes()
+ var/obj/machinery/pipes/P = line.nodes[line.numnodes]
+ P.buildnodes(null) // rebuild the local nodes of the next pipeline
+ line.vnode2 = null
+
+
+ else // pipe is somewhere in middle of pipeline - split into two
+
+ //world << "total : [line.gas.tot_gas()]"
+
+ //world << "pos [linepos] of [line.numnodes]"
+
+ var/linenodes = line.numnodes
+
+ var/obj/machinery/pipeline/newline = new()
+
+ newline.nodes = line.nodes.Copy(linepos+1)
+
+ line.nodes.Cut(linepos)
+
+ line.numnodes = linepos-1
+
+ line.capmult = 1 + line.numnodes
+
+ newline.numnodes = newline.nodes.len
+
+ plines += newline
+
+ newline.name = "pipeline #[plines.len]"
+
+ newline.capmult = 1 + newline.numnodes
+
+ for(var/obj/machinery/pipes/P in newline.nodes)
+ P.pl = newline
+
+ src.loc = null
+
+ src.node1.buildnodes(null)
+ src.node2.buildnodes(null)
+
+ line.setterm()
+ newline.setterm()
+
+ // transfer fraction of gas which will be in second line
+ newline.gas.transfer_from(line.gas, line.gas.tot_gas() * (linenodes - linepos ) / linenodes)
+
+ //world << "in 1([line.name]): [line.gas.tot_gas()]"
+ //world << "in 2([newline.name]): [newline.gas.tot_gas()]"
+
+ var/obj/substance/gas/G = new()
+
+ G.transfer_from(line.gas, line.gas.tot_gas() / (line.numnodes+1))
+
+ //world << "to turf: [G.tot_gas()]"
+
+ G.leak(T) // dump pipe's share of gas into the turf
+
+ line.ngas.replace_by(line.gas)
+ newline.ngas.replace_by(newline.gas)
+ //world << "in 1([line.name]): [line.gas.tot_gas()]"
+
+ ..() // perform actual deletion of pipe object
+
/*
* Heat_exch - Heat-exchange pipe subtype. Same as a standard pipe, but uses different icon, has lower insulation value
@@ -300,25 +546,23 @@ obj/machinery/pipes
updateicon()
+ var/turf/T = src.loc
+
var/list/dirs = get_node_dirs()
var/is = "[h_dir]"
- if(stat & BROKEN)
- is += "-b"
-
src.icon_state = is
overlays = null
- if(!node1 && !node2)
- overlays += image('pipes.dmi', "discon-he", FLY_LAYER, dirs[1])
- overlays += image('pipes.dmi', "discon-he", FLY_LAYER, dirs[2])
- else if(!node1)
- overlays += image('pipes.dmi', "discon-he", FLY_LAYER, dirs[1])
- else if(!node2)
- overlays += image('pipes.dmi', "discon-he", FLY_LAYER, dirs[2])
- return
+ if(!node1) // node1 is not connected
+ if(!findbrokenpipe(T, dirs[1], level, 1)) // no broken pipe present
+ overlays += image('pipes.dmi', "discon-he[dirs[1]]", FLY_LAYER)
+
+ else if(!node2) // node2 is not connected
+ if(!findbrokenpipe(T, dirs[2], level, 1)) // no broken pipe present
+ overlays += image('pipes.dmi', "discon-he[dirs[2]]", FLY_LAYER)
// Return list of directions corresponding to h_dir bitflags
@@ -349,6 +593,9 @@ obj/machinery/pipes
node1 = get_he_machine(level, src.loc, dirs[1])
node2 = get_he_machine(level, src.loc, dirs[2])
+ if(!line)
+ return
+
if(pl)
return
diff --git a/Code/Machinery/sec_lock.dm b/Code/Machinery/sec_lock.dm
index 2b3a977..a059f85 100644
--- a/Code/Machinery/sec_lock.dm
+++ b/Code/Machinery/sec_lock.dm
@@ -11,6 +11,7 @@ obj/machinery/sec_lock
icon = 'stationobjs.dmi'
icon_state = "sec_lock"
anchored = 1.0
+ layer = 3.1
var
obj/item/weapon/card/id/scan = null // the inserted ID card
diff --git a/Code/Machinery/valve.dm b/Code/Machinery/valve.dm
index e83da0f..849511b 100644
--- a/Code/Machinery/valve.dm
+++ b/Code/Machinery/valve.dm
@@ -63,12 +63,12 @@ obj/machinery/valve
var/turf/T = src.loc
- node1 = get_machine(level, T, dir ) // the h/e pipe
+ node1 = get_machine(level, T, dir )
- node2 = get_machine(level, T , turn(dir, 180) ) // the regular pipe
+ node2 = get_machine(level, T , turn(dir, 180) )
- if(node1) vnode1 = node1.getline()
- if(node2) vnode2 = node2.getline()
+ vnode1 = node1 ? node1.getline() : null
+ vnode2 = node2 ? node2.getline() : null
return
diff --git a/Code/Machinery/vent.dm b/Code/Machinery/vent.dm
index b4b99e8..17c7fc5 100644
--- a/Code/Machinery/vent.dm
+++ b/Code/Machinery/vent.dm
@@ -37,15 +37,9 @@ obj/machinery/vent
// Find the connected machine or pipe to the vent pipe.
buildnodes()
- var/turf/T = get_step(src.loc, src.dir)
- var/fdir = turn(src.p_dir, 180)
- for(var/obj/machinery/M in T)
- if(M.p_dir & fdir)
- src.node = M
- break
-
- if(node) vnode = node.getline()
+ node = get_machine(level, src.loc, dir)
+ vnode = node ? node.getline() : null
return
@@ -92,6 +86,16 @@ obj/machinery/vent
flow_to_turf(gas, ngas, T)
+ // Attack by item
+ // If welder, make a fitting and delete self
+
+ attackby(obj/item/weapon/W, mob/user)
+ if(istype(W, /obj/item/weapon/weldingtool))
+ if(attack_welder(W, user))
+ del(src)
+ else
+ ..()
+
obj/machinery/emergencyrelease
@@ -127,15 +131,9 @@ obj/machinery/emergencyrelease
// Find the connected machine or pipe to the vent pipe.
buildnodes()
- var/turf/T = get_step(src.loc, src.dir)
- var/fdir = turn(src.p_dir, 180)
- for(var/obj/machinery/M in T)
- if(M.p_dir & fdir)
- src.node = M
- break
-
- if(node) vnode = node.getline()
+ node = get_machine(level, src.loc, dir)
+ vnode = node ? node.getline() : null
return
@@ -235,15 +233,9 @@ obj/machinery/regulator
// Find the connected machine or pipe to the vent pipe.
buildnodes()
- var/turf/T = get_step(src.loc, src.dir)
- var/fdir = turn(src.p_dir, 180)
- for(var/obj/machinery/M in T)
- if(M.p_dir & fdir)
- src.node = M
- break
-
- if(node) vnode = node.getline()
+ node = get_machine(level, src.loc, dir)
+ vnode = node ? node.getline() : null
return
diff --git a/Code/Object/brokenpipe.dm b/Code/Object/brokenpipe.dm
new file mode 100644
index 0000000..8a75c6a
--- /dev/null
+++ b/Code/Object/brokenpipe.dm
@@ -0,0 +1,122 @@
+/*
+ * Broken Pipe -- a broken pipe object
+ *
+ * This object is substituted for a /obj/machinery/pipes object when it is broken
+ *
+ * TODO: make removable and/or repairable
+ *
+ */
+
+obj/brokenpipe
+ name = "a broken pipe"
+ icon = 'reg_pipe.dmi'
+ icon_state = "12-b"
+ anchored = 1
+
+ var/p_dir = 0 // the p_dir or h_dir of the original pipe
+
+ var/ptype = 0 // pipe type of orginal pipe
+ // 0 = regular, 1 = h/e
+
+
+ // Create a new broken pipe,
+
+ New()
+ ..()
+ updateicon()
+
+ // Set the state of the brokenpipe
+ // Copies data from the original pipe object
+
+ proc/update(var/obj/machinery/pipes/P)
+
+ ptype = 0 // defaults for regular pipe
+ p_dir = P.p_dir
+
+ if(istype(P, /obj/machinery/pipes/heat_exch)) // h/e pipe
+ ptype = 1
+ p_dir = P.h_dir
+
+ level = P.level
+
+ updateicon()
+
+
+
+ // Update the broken pipe icon depending on the pipe dirs and type
+
+ proc/updateicon()
+ var/is
+
+ switch(ptype)
+ if(0)
+ icon = 'reg_pipe.dmi'
+ is = "[p_dir]-b"
+ if(1)
+ icon = 'heat_pipe.dmi'
+ is = "[p_dir]-b"
+
+
+ var/turf/T = src.loc
+
+ if ((src.level == 1 && isturf(T) && T.intact))
+ src.invisibility = 101
+ is += "-f"
+
+ else
+ src.invisibility = null
+
+ icon_state = is
+ return
+
+ // Called when a pipe is revealed or hidden when a floor tile is removed, etc.
+ // Just call updateicon(), since all is handled there already
+
+ hide(var/i)
+ updateicon()
+
+
+ // attack with item
+ // if welder, delete the pipe
+
+ attackby(obj/item/weapon/W, mob/user)
+
+ if (istype(W, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/WT = W
+ if(WT.welding)
+
+ if(WT.weldfuel > 2)
+ WT.weldfuel -=2
+
+ user.client_mob() << "\blue Removing the broken pipe. Stand still as this takes some time."
+ var/turf/T = user.loc
+ sleep(30)
+
+ if ((user.loc == T && user.equipped() == W))
+
+ del(src)
+ else
+ user.client_mob() << "\blue You need more welding fuel to remove the pipe."
+ else
+ ..()
+ return
+
+// Global proc - look for a matching broken pipe
+// step direction dirn from turf OT
+// must match level and ptype
+// returns true if found, false otherwise
+
+proc/findbrokenpipe(var/turf/OT, var/dirn, var/lev, var/pipetype)
+
+ var/turf/T = get_step(OT, dirn) // look in this turf
+
+ var/flipdir = turn(dirn,180) // for brokenpipe matching this pdir
+
+ for(var/obj/brokenpipe/BP in T)
+ if(BP.p_dir & flipdir)
+ if(BP.level == lev && BP.ptype == pipetype)
+ return 1 // found a matching brokenpipe
+
+ return 0 // found no match
+
+
diff --git a/Code/_debug.dm b/Code/_debug.dm
index e51d6ec..80cb946 100644
--- a/Code/_debug.dm
+++ b/Code/_debug.dm
@@ -472,4 +472,17 @@
//Pops up the take-off / put-on dialog, but for yourself.
/mob/human/proc/ShowMyInv()
+ set category = "Debug"
src.show_inv(src)
+
+// Show all admins
+/mob/verb/Admins()
+ set category = "Debug"
+
+ for(var/A in admins)
+ world << "[A] = [admins[A]]"
+
+/mob/verb/plasma()
+ set category = "Debug"
+
+ new /obj/machinery/atmoalter/canister/poisoncanister(src.loc)
\ No newline at end of file
diff --git a/Code/cell_process.dm b/Code/cell_process.dm
index 3b5fe44..328eca0 100644
--- a/Code/cell_process.dm
+++ b/Code/cell_process.dm
@@ -895,6 +895,10 @@ turf/proc/tot_old_gas()
/turf/proc/tot_tmp_gas()
return tmpco2 + tmpoxy + tmppoison + tsl_gas + tn2
+// return the "pressure" of a turf
+
+/turf/proc/pressure()
+ return src.tot_gas() * src.temp
// return the gas contents of a turf as a gas obj
diff --git a/Code/chemical.dm b/Code/chemical.dm
index 722a7f7..117c40e 100644
--- a/Code/chemical.dm
+++ b/Code/chemical.dm
@@ -82,7 +82,6 @@
return
/obj/substance/proc/leak(turf)
-
return
/obj/substance/chemical/proc/volume()
@@ -219,10 +218,9 @@ heat is conserved between exchanges
#define TURF_ADD_FRAC 0.95 //cooling due to release of gas into tile
#define TURF_TAKE_FRAC 1.06 //heating due to pressurization into pipework
-// Not used?
/obj/substance/gas/leak(T as turf)
- turf_add(T, src.co2 + src.oxygen + src.plasma + src.n2)
+ turf_add(T, -1)
return
diff --git a/Code/computer.dm b/Code/computer.dm
index b0a2218..f812a37 100644
--- a/Code/computer.dm
+++ b/Code/computer.dm
@@ -170,9 +170,10 @@
step(user.pulling, get_dir(user.pulling.loc, src))
return
-/turf/space/attackby(obj/item/weapon/tile/T as obj, mob/user as mob)
+/turf/space/attackby(obj/item/weapon/W, mob/user)
- if (istype(T, /obj/item/weapon/tile))
+ if (istype(W, /obj/item/weapon/tile))
+ var/obj/item/weapon/tile/T = W
T.build(src)
T.amount--
T.add_fingerprint(user)
@@ -180,6 +181,10 @@
user.u_equip(T)
del(T)
return
+ else if (istype(W, /obj/item/weapon/pipe) )
+ var/obj/item/weapon/pipe/pipe = W
+ if(locate(/obj/lattice) in src)
+ pipe.turf_place(src, user)
return
/turf/space/updatecell()
diff --git a/Code/datumvars.dm b/Code/datumvars.dm
index cc35b66..a2ee4ba 100644
--- a/Code/datumvars.dm
+++ b/Code/datumvars.dm
@@ -23,7 +23,7 @@
dat += variable(usr, V, D.vars[V]) //get the text for that variable
dat += "