mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-05-17 20:30:46 +01:00
3d9f826467
* name clarity and fix * debug text * op
469 lines
11 KiB
Plaintext
469 lines
11 KiB
Plaintext
// Disposal pipes
|
|
/obj/structure/disposalpipe
|
|
icon = 'icons/obj/pipes/disposal.dmi'
|
|
name = "disposal pipe"
|
|
desc = "An underfloor disposal pipe."
|
|
anchored = TRUE
|
|
density = FALSE
|
|
unacidable = TRUE
|
|
|
|
level = 1 // underfloor only
|
|
var/dpdir = 0 // bitmask of pipe directions
|
|
dir = 0 // dir will contain dominant direction for junction pipes
|
|
var/health = 10 // health points 0-10
|
|
plane = PLATING_PLANE
|
|
layer = DISPOSAL_LAYER // slightly lower than wires and other pipes
|
|
var/base_icon_state // initial icon state on map
|
|
var/sortType = ""
|
|
var/subtype = 0
|
|
|
|
// new pipe, set the icon_state as on map
|
|
/obj/structure/disposalpipe/Initialize(mapload)
|
|
. = ..()
|
|
base_icon_state = icon_state
|
|
|
|
// pipe is deleted
|
|
// ensure if holder is present, it is expelled
|
|
/obj/structure/disposalpipe/Destroy()
|
|
var/obj/structure/disposalholder/H = locate() in src
|
|
if(H)
|
|
// holder was present
|
|
H.active = FALSE
|
|
var/turf/T = get_turf(src)
|
|
if(T.density)
|
|
// deleting pipe is inside a dense turf (wall)
|
|
// this is unlikely, but just dump out everything into the turf in case
|
|
|
|
for(var/atom/movable/AM in H)
|
|
AM.forceMove(T)
|
|
AM.pipe_eject(0)
|
|
qdel(H)
|
|
..()
|
|
return
|
|
|
|
// otherwise, do normal expel from turf
|
|
if(H)
|
|
pipe_expel(H, T, 0)
|
|
. = ..()
|
|
|
|
// returns the direction of the next pipe object, given the entrance dir
|
|
// by default, returns the bitmask of remaining directions
|
|
/obj/structure/disposalpipe/proc/nextdir(var/fromdir)
|
|
return dpdir & (~turn(fromdir, 180))
|
|
|
|
// transfer the holder through this pipe segment
|
|
// overriden for special behaviour
|
|
/obj/structure/disposalpipe/proc/transfer(var/obj/structure/disposalholder/H)
|
|
var/nextdir = nextdir(H.dir)
|
|
H.set_dir(nextdir)
|
|
var/turf/T = H.nextloc()
|
|
var/obj/structure/disposalpipe/P = H.findpipe(T)
|
|
|
|
if(P)
|
|
// find other holder in next loc, if inactive merge it with current
|
|
var/obj/structure/disposalholder/H2 = locate() in P
|
|
if(H2 && !H2.active)
|
|
H.merge(H2)
|
|
|
|
H.forceMove(P)
|
|
else // if wasn't a pipe, then set loc to turf
|
|
H.forceMove(T)
|
|
return null
|
|
|
|
return P
|
|
|
|
|
|
// update the icon_state to reflect hidden status
|
|
/obj/structure/disposalpipe/proc/update()
|
|
var/turf/T = get_turf(src)
|
|
hide(!T.is_plating() && !istype(T,/turf/space)) // space never hides pipes
|
|
|
|
// hide called by levelupdate if turf intact status changes
|
|
// change visibility status and force update of icon
|
|
/obj/structure/disposalpipe/hide(var/intact)
|
|
invisibility = intact ? INVISIBILITY_ABSTRACT : INVISIBILITY_NONE // hide if floor is intact
|
|
update_icon()
|
|
|
|
// update actual icon_state depending on visibility
|
|
// if invisible, append "f" to icon_state to show faded version
|
|
// this will be revealed if a T-scanner is used
|
|
// if visible, use regular icon_state
|
|
/obj/structure/disposalpipe/update_icon()
|
|
if(!(flags & ATOM_INITIALIZED)) // Do not call update_icon before init. E.g. hide might be called before
|
|
return
|
|
/* if(invisibility) //we hide things with alpha now, no need for transparent icons
|
|
icon_state = "[base_icon_state]f"
|
|
else
|
|
icon_state = base_icon_state*/
|
|
icon_state = base_icon_state
|
|
return
|
|
|
|
|
|
// expel the held objects into a turf
|
|
// called when there is a break in the pipe
|
|
/obj/structure/disposalpipe/proc/pipe_expel(obj/structure/disposalholder/H, turf/T, direction)
|
|
if(!istype(H))
|
|
return
|
|
|
|
// Empty the holder if it is expelled into a dense turf.
|
|
// Leaving it intact and sitting in a wall is stupid.
|
|
if(T.density)
|
|
for(var/atom/movable/AM in H)
|
|
AM.loc = T
|
|
AM.pipe_eject(0)
|
|
qdel(H)
|
|
return
|
|
|
|
if(!T.is_plating() && istype(T,/turf/simulated/floor)) //intact floor, pop the tile
|
|
var/turf/simulated/floor/F = T
|
|
F.make_plating(TRUE)
|
|
|
|
var/turf/target
|
|
if(direction) // direction is specified
|
|
if(istype(T, /turf/space)) // if ended in space, then range is unlimited
|
|
target = get_edge_target_turf(T, direction)
|
|
else // otherwise limit to 10 tiles
|
|
target = get_ranged_target_turf(T, direction, 10)
|
|
|
|
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
|
|
if(H)
|
|
for(var/atom/movable/AM in H)
|
|
if(QDELETED(AM))
|
|
continue
|
|
AM.forceMove(T)
|
|
AM.pipe_eject(direction)
|
|
AM.throw_at(target, 100, 1)
|
|
|
|
H.vent_gas(T)
|
|
qdel(H)
|
|
|
|
else // no specified direction, so throw in random direction
|
|
|
|
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
|
|
if(H)
|
|
for(var/atom/movable/AM in H)
|
|
if(QDELETED(AM))
|
|
continue
|
|
target = get_offset_target_turf(T, rand(5)-rand(5), rand(5)-rand(5))
|
|
AM.forceMove(T)
|
|
AM.pipe_eject(0)
|
|
AM.throw_at(target, 5, 1)
|
|
|
|
H.vent_gas(T) // all gas vent to turf
|
|
qdel(H)
|
|
|
|
return
|
|
|
|
// call to break the pipe
|
|
// will expel any holder inside at the time
|
|
// then delete the pipe
|
|
// remains : set to leave broken pipe pieces in place
|
|
/obj/structure/disposalpipe/proc/broken(remains = 0)
|
|
if(remains)
|
|
for(var/D in GLOB.cardinal)
|
|
if(D & dpdir)
|
|
var/obj/structure/disposalpipe/broken/P = new(get_turf(src))
|
|
P.set_dir(D)
|
|
|
|
invisibility = INVISIBILITY_ABSTRACT // make invisible (since we won't delete the pipe immediately)
|
|
var/obj/structure/disposalholder/H = locate() in src
|
|
if(H)
|
|
// holder was present
|
|
H.active = FALSE
|
|
var/turf/T = get_turf(src)
|
|
if(T.density)
|
|
// broken pipe is inside a dense turf (wall)
|
|
// this is unlikely, but just dump out everything into the turf in case
|
|
|
|
for(var/atom/movable/AM in H)
|
|
AM.forceMove(T)
|
|
AM.pipe_eject(0)
|
|
qdel(H)
|
|
return
|
|
|
|
// otherwise, do normal expel from turf
|
|
if(H)
|
|
pipe_expel(H, T, 0)
|
|
|
|
spawn(2) // delete pipe after 2 ticks to ensure expel proc finished
|
|
qdel(src)
|
|
|
|
|
|
// pipe affected by explosion
|
|
/obj/structure/disposalpipe/ex_act(severity)
|
|
|
|
switch(severity)
|
|
if(1.0)
|
|
broken(0)
|
|
return
|
|
if(2.0)
|
|
health -= rand(5,15)
|
|
healthcheck()
|
|
return
|
|
if(3.0)
|
|
health -= rand(0,15)
|
|
healthcheck()
|
|
return
|
|
|
|
|
|
// test health for brokenness
|
|
/obj/structure/disposalpipe/proc/healthcheck()
|
|
if(health < -2)
|
|
broken(0)
|
|
else if(health<1)
|
|
broken(1)
|
|
return
|
|
|
|
//attack by item
|
|
//weldingtool: unfasten and convert to obj/disposalconstruct
|
|
/obj/structure/disposalpipe/attackby(obj/item/I, mob/user)
|
|
|
|
var/turf/T = get_turf(src)
|
|
if(!T.is_plating())
|
|
return // prevent interaction with T-scanner revealed pipes
|
|
add_fingerprint(user)
|
|
if(I.has_tool_quality(TOOL_WELDER))
|
|
var/obj/item/weldingtool/W = I.get_welder()
|
|
if(W.remove_fuel(0,user))
|
|
playsound(src, W.usesound, 100, 1)
|
|
to_chat(user, "You start slicing [src]....")
|
|
if(do_after(user, 2 SECONDS * W.toolspeed, target = src))
|
|
if(!src || !W.isOn()) return
|
|
to_chat(user, "You slice [src]")
|
|
welded()
|
|
else
|
|
to_chat(user, "You must stay still while welding the pipe.")
|
|
else
|
|
to_chat(user, "You need more welding fuel to cut the pipe.")
|
|
return
|
|
|
|
// called when pipe is cut with welder
|
|
/obj/structure/disposalpipe/proc/welded()
|
|
|
|
var/obj/structure/disposalconstruct/C = new (get_turf(src))
|
|
switch(base_icon_state)
|
|
if("pipe-s")
|
|
C.ptype = 0
|
|
if("pipe-c")
|
|
C.ptype = 1
|
|
if("pipe-j1")
|
|
C.ptype = 2
|
|
if("pipe-j2")
|
|
C.ptype = 3
|
|
if("pipe-y")
|
|
C.ptype = 4
|
|
if("pipe-t")
|
|
C.ptype = 5
|
|
if("pipe-j1s")
|
|
C.ptype = 9
|
|
C.sortType = sortType
|
|
if("pipe-j2s")
|
|
C.ptype = 10
|
|
C.sortType = sortType
|
|
///// Z-Level stuff
|
|
if("pipe-u")
|
|
C.ptype = 11
|
|
if("pipe-d")
|
|
C.ptype = 12
|
|
///// Z-Level stuff
|
|
if("pipe-tagger")
|
|
C.ptype = 13
|
|
if("pipe-tagger-partial")
|
|
C.ptype = 14
|
|
C.subtype = subtype
|
|
transfer_fingerprints_to(C)
|
|
C.set_dir(dir)
|
|
C.density = FALSE
|
|
C.anchored = TRUE
|
|
C.update()
|
|
|
|
qdel(src)
|
|
|
|
// pipe is deleted
|
|
// ensure if holder is present, it is expelled
|
|
/obj/structure/disposalpipe/Destroy()
|
|
var/obj/structure/disposalholder/H = locate() in src
|
|
if(H)
|
|
// holder was present
|
|
H.active = FALSE
|
|
var/turf/T = get_turf(src)
|
|
if(T.density)
|
|
// deleting pipe is inside a dense turf (wall)
|
|
// this is unlikely, but just dump out everything into the turf in case
|
|
|
|
for(var/atom/movable/AM in H)
|
|
AM.forceMove(T)
|
|
AM.pipe_eject(0)
|
|
qdel(H)
|
|
..()
|
|
return
|
|
|
|
// otherwise, do normal expel from turf
|
|
if(H)
|
|
pipe_expel(H, T, 0)
|
|
. = ..()
|
|
|
|
/obj/structure/disposalpipe/hides_under_flooring()
|
|
return 1
|
|
|
|
// *** TEST verb
|
|
//client/verb/dispstop()
|
|
// for(var/obj/structure/disposalholder/H in world)
|
|
// H.active = 0
|
|
|
|
// a straight or bent segment
|
|
/obj/structure/disposalpipe/segment
|
|
icon_state = "pipe-s"
|
|
|
|
/obj/structure/disposalpipe/segment/Initialize(mapload)
|
|
. = ..()
|
|
if(icon_state == "pipe-s")
|
|
dpdir = dir | turn(dir, 180)
|
|
else
|
|
dpdir = dir | turn(dir, -90)
|
|
|
|
update()
|
|
|
|
|
|
|
|
///// Z-Level stuff
|
|
/obj/structure/disposalpipe/up
|
|
icon_state = "pipe-u"
|
|
|
|
/obj/structure/disposalpipe/up/Initialize(mapload)
|
|
. = ..()
|
|
dpdir = dir
|
|
update()
|
|
|
|
/obj/structure/disposalpipe/up/nextdir(fromdir)
|
|
var/nextdir
|
|
if(fromdir == 11)
|
|
nextdir = dir
|
|
else
|
|
nextdir = 12
|
|
return nextdir
|
|
|
|
/obj/structure/disposalpipe/up/transfer(obj/structure/disposalholder/H)
|
|
var/nextdir = nextdir(H.dir)
|
|
H.set_dir(nextdir)
|
|
|
|
var/turf/T
|
|
var/obj/structure/disposalpipe/P
|
|
|
|
if(nextdir == 12)
|
|
T = GetAbove(src)
|
|
if(!T)
|
|
H.forceMove(loc)
|
|
return
|
|
else
|
|
for(var/obj/structure/disposalpipe/down/F in T)
|
|
P = F
|
|
|
|
else
|
|
T = get_step(get_turf(src), H.dir)
|
|
P = H.findpipe(T)
|
|
|
|
if(P)
|
|
// find other holder in next loc, if inactive merge it with current
|
|
var/obj/structure/disposalholder/H2 = locate() in P
|
|
if(H2 && !H2.active)
|
|
H.merge(H2)
|
|
|
|
H.forceMove(P)
|
|
else // if wasn't a pipe, then set loc to turf
|
|
H.forceMove(T)
|
|
return null
|
|
|
|
return P
|
|
|
|
/obj/structure/disposalpipe/down
|
|
icon_state = "pipe-d"
|
|
|
|
/obj/structure/disposalpipe/down/Initialize(mapload)
|
|
. = ..()
|
|
dpdir = dir
|
|
update()
|
|
|
|
/obj/structure/disposalpipe/down/nextdir(fromdir)
|
|
var/nextdir
|
|
if(fromdir == 12)
|
|
nextdir = dir
|
|
else
|
|
nextdir = 11
|
|
return nextdir
|
|
|
|
/obj/structure/disposalpipe/down/transfer(obj/structure/disposalholder/H)
|
|
var/nextdir = nextdir(H.dir)
|
|
H.dir = nextdir
|
|
|
|
var/turf/T
|
|
var/obj/structure/disposalpipe/P
|
|
|
|
if(nextdir == 11)
|
|
T = GetBelow(src)
|
|
if(!T)
|
|
H.forceMove(get_turf(src))
|
|
return
|
|
else
|
|
for(var/obj/structure/disposalpipe/up/F in T)
|
|
P = F
|
|
|
|
else
|
|
T = get_step(get_turf(src), H.dir)
|
|
P = H.findpipe(T)
|
|
|
|
if(P)
|
|
// find other holder in next loc, if inactive merge it with current
|
|
var/obj/structure/disposalholder/H2 = locate() in P
|
|
if(H2 && !H2.active)
|
|
H.merge(H2)
|
|
|
|
H.forceMove(P)
|
|
else // if wasn't a pipe, then set loc to turf
|
|
H.forceMove(T)
|
|
return null
|
|
|
|
return P
|
|
|
|
|
|
|
|
// a broken pipe
|
|
/obj/structure/disposalpipe/broken
|
|
icon_state = "pipe-b"
|
|
dpdir = 0 // broken pipes have dpdir=0 so they're not found as 'real' pipes
|
|
// i.e. will be treated as an empty turf
|
|
desc = "A broken piece of disposal pipe."
|
|
|
|
/obj/structure/disposalpipe/broken/Initialize(mapload)
|
|
. = ..()
|
|
update()
|
|
|
|
// called when welded
|
|
/obj/structure/disposalpipe/broken/welded()
|
|
qdel(src)
|
|
|
|
// called when movable is expelled from a disposal pipe or outlet
|
|
// by default does nothing, override for special behaviour
|
|
/atom/movable/proc/pipe_eject(direction)
|
|
return
|
|
|
|
// check if mob has client, if so restore client view on eject
|
|
/mob/pipe_eject(var/direction)
|
|
reset_perspective()
|
|
|
|
/obj/effect/decal/cleanable/blood/gibs/pipe_eject(direction)
|
|
var/list/dirs
|
|
if(direction)
|
|
dirs = list( direction, turn(direction, -45), turn(direction, 45))
|
|
else
|
|
dirs = GLOB.alldirs.Copy()
|
|
streak(dirs)
|
|
|
|
/obj/effect/decal/cleanable/blood/gibs/robot/pipe_eject(direction)
|
|
var/list/dirs
|
|
if(direction)
|
|
dirs = list( direction, turn(direction, -45), turn(direction, 45))
|
|
else
|
|
dirs = GLOB.alldirs.Copy()
|
|
streak(dirs)
|